diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 000000000..c367af78c
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,17 @@
+# Get workspace status information to stamp into the build.
+build --workspace_status_command=build/workspace_status.sh
+
+# Enable build stamping to inject the workspace status variables.
+build --stamp
+
+# verbose go_test logs for buildbuddy to get more details on test behaviour
+test --test_env=GO_TEST_WRAP_TESTV=1
+
+
+build:remotecache --bes_results_url=https://app.buildbuddy.io/invocation/
+build:remotecache --bes_backend=grpcs://remote.buildbuddy.io
+common:remotecache --remote_cache=grpcs://remote.buildbuddy.io
+common:remotecache --noremote_upload_local_results # Uploads logs & artifacts without writing to cache
+common:remotecache --remote_timeout=10m
+common:remotecache --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}
+
diff --git a/.bazelversion b/.bazelversion
new file mode 100644
index 000000000..8104cabd3
--- /dev/null
+++ b/.bazelversion
@@ -0,0 +1 @@
+8.1.0
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9535d21b4..a1a739c1b 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1 +1,6 @@
+# All files are by default owned unless a more specific rule set below.
* @jaqx0r
+
+# Don't automatically assign reviewers for PRs that only modify these files.
+go.mod
+go.sum
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..0a30f0223
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: ["jaqx0r"]
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 66915d899..81aeb6021 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -15,7 +15,7 @@ If your problem is with the way an `mtail` program is behaving, please attach or
If your problem is with `mtail`, please include the commandline you started it with, and the INFO log.
-See also [Reporting a problem](https://github.com/google/mtail/blob/main/docs/Troubleshooting.md#reporting-a-problem).
+See also [Reporting a problem](https://github.com/jaqx0r/mtail/blob/main/docs/Troubleshooting.md#reporting-a-problem).
Thanks!
diff --git a/.github/actions/bazel-benchmark/action.yml b/.github/actions/bazel-benchmark/action.yml
new file mode 100644
index 000000000..8ef553057
--- /dev/null
+++ b/.github/actions/bazel-benchmark/action.yml
@@ -0,0 +1,38 @@
+# Run benchmark tests under bazel
+# Assumes bazel exists, use `bazel-contrib/setup-bazel` before calling this action.
+name: bazel benchmark
+description: Run benchmarks under Bazel and save output
+inputs:
+ build_tag_filters:
+ description: Tag to filter on to find benchmarks to build
+ required: true
+ default: benchmark
+ targets:
+ description: Bazel targets to build
+ required: true
+ default: //...
+ bazel_run_flags:
+ description: Flags to pass to Bazel to run the benchmarks
+ required: true
+ default: -test.bench=.*
+ output_artifact:
+ description: Name of the output artifact
+ required: true
+ default: benchmark_results.txt
+runs:
+ using: composite
+ steps:
+ - name: build benchmarks
+ run: bazel build --build_tag_filters=${{ inputs.build_tag_filters }} ${{ inputs.targets }}
+ shell: bash
+ - name: run benchmarks
+ shell: bash
+ run: |
+ for target in $(bazel query "attr(tags, '\\b${{ inputs.build_tag_filters }}\\b', ${{ inputs.targets }})"); do
+ bazel run ${target} -- ${{ inputs.bazel_run_flags }}
+ done | tee benchmark_results.txt
+ - name: upload benchmark results artfact
+ uses: actions/upload-artifact@v7
+ with:
+ name: ${{ inputs.output_artifact }}
+ path: benchmark_results.txt
diff --git a/.github/actions/bencher-run/action.yml b/.github/actions/bencher-run/action.yml
new file mode 100644
index 000000000..d330a7004
--- /dev/null
+++ b/.github/actions/bencher-run/action.yml
@@ -0,0 +1,61 @@
+# Run bencher on a benchmark result artifact.
+# Assumes BENCHER_API_TOKEN and GITHUB_TOKEN secrets exist.
+
+name: bencher run
+description: Run bencher on a benchmark result artifact
+inputs:
+ BENCHER_API_TOKEN:
+ description: Token to interact with Bencher.dev; https://bencher.dev/docs/explanation/bencher-run/#--token-token
+ required: true
+ benchmark_results_artifact:
+ description: Name of the artifact to download, to find the benchmark results within.
+ required: true
+ default: benchmark_results.txt
+ workflow_event:
+ description: Name of the workflow trigger event json to download
+ required: true
+ default: event.json
+ project:
+ required: true
+ description: Project slug or UUID for Bencher.dev; https://bencher.dev/docs/explanation/bencher-run/#--project-project
+runs:
+ using: composite
+ steps:
+ - uses: bencherdev/bencher@main
+ - uses: actions/download-artifact@v8
+ with:
+ name: ${{ inputs.benchmark_results_artifact }}
+ run-id: ${{ github.event.workflow_run.id }}
+ github-token: ${{ github.token }}
+ - uses: actions/download-artifact@v8
+ with:
+ name: ${{ inputs.workflow_event }}
+ run-id: ${{ github.event.workflow_run.id }}
+ github-token: ${{ github.token }}
+ - uses: actions/github-script@v9
+ env:
+ EVT: ${{ inputs.workflow_event }}
+ with:
+ script: |
+ let fs = require('fs');
+ let event = JSON.parse(fs.readFileSync(process.env.EVT, {encoding: 'utf8'}));
+ flags = [];
+ if (!!event.pull_request) {
+ flags.push("--branch", event.pull_request.head.ref);
+ flags.push("--hash", event.pull_request.head.sha);
+ flags.push("--start-point", event.pull_request.base.ref);
+ flags.push("--start-point-hash", event.pull_request.head.sha);
+ flags.push("--start-point-clone-thresholds")
+ flags.push("--start-point-reset")
+ flags.push("--ci-number", event.number);
+ }
+ core.exportVariable("BENCHER_FLAGS", flags.join(" "));
+ - name: bencher run
+ shell: bash
+ run: |
+ bencher run \
+ --token '${{ inputs.BENCHER_API_TOKEN }}' \
+ --github-actions '${{ github.token }}' \
+ --project '${{ inputs.project }}' \
+ $BENCHER_FLAGS \
+ --file ${{ inputs.benchmark_results_artifact }}
diff --git a/.github/workflows/auto-approve.yaml b/.github/workflows/auto-approve.yaml
new file mode 100644
index 000000000..83822a55d
--- /dev/null
+++ b/.github/workflows/auto-approve.yaml
@@ -0,0 +1,27 @@
+# We "trust" dependabot and renovate updates once they pass tests.
+# (this still requires all other checks to pass!)
+
+# This doesn't work on forked repos per the discussion in
+# https://github.com/pascalgn/automerge-action/issues/46 so don't attempt to
+# add people other than dependabot to the if field below.
+name: auto-approve
+on:
+ workflow_run:
+ workflows:
+ - ci
+ types:
+ - completed
+
+jobs:
+ enable-automerge-and-approve:
+ if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.pull_requests[0] && (github.event.workflow_run.actor.login == 'dependabot[bot]' || github.event.workflow_run.actor.login == 'renovate[bot]')
+ runs-on: ubuntu-latest
+ # https://github.com/orgs/community/discussions/24686
+ permissions:
+ contents: write
+ pull-requests: write
+ env:
+ GH_TOKEN: ${{ github.token }}
+ steps:
+ - run: gh pr merge ${{ github.event.workflow_run.pull_requests[0].number }} --auto
+ - run: gh pr review ${{ github.event.workflow_run.pull_requests[0].number }} --approve
diff --git a/.github/workflows/auto-review.yml b/.github/workflows/auto-review.yml
index cec2e03ed..ec9f76569 100644
--- a/.github/workflows/auto-review.yml
+++ b/.github/workflows/auto-review.yml
@@ -30,14 +30,14 @@ jobs:
# create review
pull-requests: write
steps:
- - uses: lewagon/wait-on-check-action@v1.3.4
+ - uses: lewagon/wait-on-check-action@v1.7.0
with:
ref: ${{ github.event.pull_request.head.sha }}
repo-token: ${{ github.token }}
check-regexp: "test.*"
wait-interval: 60
- - uses: "actions/github-script@v7"
+ - uses: "actions/github-script@v9"
with:
github-token: ${{ github.token }}
script: |
diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml
index aa12eae84..539b5deeb 100644
--- a/.github/workflows/automerge.yml
+++ b/.github/workflows/automerge.yml
@@ -40,7 +40,7 @@ jobs:
# wait-on-check requires only checks read
checks: read
steps:
- - uses: lewagon/wait-on-check-action@v1.3.4
+ - uses: lewagon/wait-on-check-action@v1.7.0
with:
ref: ${{ github.event.pull_request.head.sha }}
check-regexp: "test.*"
@@ -55,6 +55,6 @@ jobs:
# auto-approve-action requires write on pull-requests
pull-requests: write
steps:
- - uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363
+ - uses: hmarr/auto-approve-action@8f929096a962e83ccdfa8afcf855f39f12d4dac7
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/benchmark-upload.yml b/.github/workflows/benchmark-upload.yml
new file mode 100644
index 000000000..e8087e45f
--- /dev/null
+++ b/.github/workflows/benchmark-upload.yml
@@ -0,0 +1,26 @@
+name: benchmark-upload
+
+on:
+ workflow_run:
+ workflows:
+ - benchmark
+ types:
+ - completed
+
+jobs:
+ bencher-upload:
+ if: github.event.workflow_run.conclusion == 'success'
+ runs-on: ubuntu-latest
+ permissions:
+ # Allow bencher-run to write to the PR comments
+ pull-requests: write
+ # Allow bencher-run to read the benchmark results artifact
+ actions: read
+ # Allow bencher-run to write to the checks api
+ checks: write
+ steps:
+ - uses: actions/checkout@v6
+ - uses: ./.github/actions/bencher-run
+ with:
+ BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
+ project: 238e7993-fc7a-4a69-aa82-470abd249c8b
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
index 6ffc3035e..77d1f79bb 100644
--- a/.github/workflows/benchmark.yml
+++ b/.github/workflows/benchmark.yml
@@ -7,32 +7,26 @@ on:
# Record on merges to main
- main
+permissions: {}
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
benchmark:
- if: ${{ false }}
runs-on: ubuntu-latest
permissions:
- # For benchmark-action comment-always
- pull-requests: write
+ contents: read
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version-file: 'go.mod'
- cache: true
- - run: make bench
- env:
- HEAD_REF: ${{ env.GITHUB_REF_NAME }}
- - uses: actions/cache@v4
+ - uses: actions/checkout@v6
+ - uses: bazel-contrib/setup-bazel@0.19.0
with:
- path: ./cache
- key: ${{ runner.os }}-benchmark
- - uses: benchmark-action/github-action-benchmark@v1.20.3
+ bazelisk-cache: true
+ disk-cache: ${{ github.workflow }}
+ repository-cache: true
+ - uses: ./.github/actions/bazel-benchmark
+ - uses: actions/upload-artifact@v7
with:
- tool: 'go'
- output-file-path: test-results/benchmark-results-${{ env.GITHUB_REF_NAME }}.txt
- external-data-json-path: ./cache/benchmark-data.json
- save-data-file: ${{ github.event_name != 'pull_request' }}
- github-token: ${{ secrets.GITHUB_TOKEN }}
- comment-on-alert: true
- summary-always: true
+ name: event.json
+ path: ${{ github.event_path }}
diff --git a/.github/workflows/ci-done.yml b/.github/workflows/ci-done.yml
deleted file mode 100644
index c4633549a..000000000
--- a/.github/workflows/ci-done.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-name: Comment CI test results on PR
-on:
- workflow_run:
- workflows: ["CI"]
- types:
- - completed
-jobs:
- comment:
- strategy:
- matrix:
- # Sync with matrix in ci.yml
- runs-on: [ubuntu-latest]
- runs-on: ${{ matrix.runs-on }}
- permissions:
- # list and download
- actions: read
- # post results as comment
- pull-requests: write
- # publish creates a check run
- checks: write
- steps:
- - uses: actions/github-script@v7
- with:
- script: |
- var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
- owner: context.repo.owner,
- repo: context.repo.repo,
- run_id: ${{github.event.workflow_run.id }},
- });
- var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
- return artifact.name == "test-results-${{ matrix.runs-on }}"
- })[0];
- var download = await github.rest.actions.downloadArtifact({
- owner: context.repo.owner,
- repo: context.repo.repo,
- artifact_id: matchArtifact.id,
- archive_format: 'zip',
- });
- var fs = require('fs');
- fs.writeFileSync('${{github.workspace}}/test-results.zip', Buffer.from(download.data));
- - id: unpack
- run: |
- mkdir -p test-results
- unzip -d test-results test-results.zip
- echo "sha=$(cat test-results/sha-number)" >> $GITHUB_OUTPUT
- - uses: EnricoMi/publish-unit-test-result-action@v2
- with:
- commit: ${{ steps.unpack.outputs.sha }}
- check_name: Unit Test Results
- github_token: ${{ secrets.GITHUB_TOKEN }}
- files: "**/test-results/**/*.xml"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d3718af7b..8fd50ecfa 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,15 +1,22 @@
-name: CI
+name: ci
+
on:
push:
tags:
- - v*
branches:
- main
pull_request:
merge_group:
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
env:
GOPROXY: "https://proxy.golang.org"
+# Lock down default permissions to no permissions.
permissions:
# none-all, which doesn't exist, but
# https://docs.github.com/en/actions/reference/authentication-in-a-workflow#using-the-github_token-in-a-workflow
@@ -19,88 +26,42 @@ permissions:
jobs:
test:
- strategy:
- matrix:
- # macos-latest is slow and has weird test failures with unixgram message sizes, so it's been disabled.
- # Sync with matrix in ci-done.yml
- runs-on: [ubuntu-latest, windows-latest]
- runs-on: ${{ matrix.runs-on }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version-file: 'go.mod'
- cache: true
- - name: install deps
- run: go mod download
- - name: build
- run: make --debug all
- - name: test
- run: |
- mkdir -p test-results
- # Don't use GITHUB_SHA as we need the head of the branch, not the
- # secret merge commit of the PR itself. https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#pull-request-event-pull_request
- if [[ ${{ github.event_name }} == 'pull_request' ]]; then
- echo ${{ github.event.pull_request.head.sha }} > test-results/sha-number
- else
- echo ${{ github.sha }} > test-results/sha-number
- fi
- make --debug junit-regtest TESTCOVERPROFILE=coverprofile
- shell: bash
- - uses: codecov/codecov-action@v4
- if: always()
- with:
- file: coverprofile
- - uses: actions/upload-artifact@v4
- if: always()
- with:
- name: test-results-${{ matrix.runs-on }}
- path: test-results/
-
- container:
runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0 # so that we get tags
- - run: make --debug container
-
- gosec:
- runs-on: ubuntu-latest
- # gosec is regularly broken and reporting false positives, don't let it interfere
- continue-on-error: true
permissions:
- security-events: write
+ # publish-unit-test-result-action writes a comment to the PR
+ pull-requests: write
+ # and writes to the checks API
+ checks: write
steps:
- - uses: actions/checkout@v4
- - uses: securego/gosec@master
+ - uses: actions/checkout@v6
with:
- # we let the report trigger content trigger a failure using the GitHub Security features.
- args: '-no-fail -exclude-generated -fmt sarif -out results.sarif -tags fuzz ./...'
- - uses: github/codeql-action/upload-sarif@v3
+ fetch-depth: 1
+ fetch-tags: true
+ - uses: bazel-contrib/setup-bazel@0.19.0
with:
- # Path to SARIF file relative to the root of the repository
- sarif_file: results.sarif
-
-
- fuzz:
- runs-on: ubuntu-latest
- container:
- image: gcr.io/oss-fuzz-base/base-builder
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ # Avoid downloading Bazel each time
+ bazelisk-cache: true
+ # Store build cache per workflow
+ disk-cache: ${{ github.workflow }}
+ # Share repository cache between workflows
+ repository-cache: true
+ - name: bazel build
+ # Speed up CI build by only doing compilation outputs
+ run: bazel build --output_groups=compilation_outputs //...
+ - name: bazel test
+ run: bazel coverage --test_output=all --combined_report=lcov --instrument_test_targets --nocache_test_results --instrumentation_filter="^//" //...
+ - name: output bazel paths for test and coverage
+ if: always()
+ id: bazel_info
+ run: |
+ bazel info bazel-testlogs output_path | sed -e 's/: /=/' >> $GITHUB_OUTPUT
+ - uses: EnricoMi/publish-unit-test-result-action/linux@v2
+ if: (!cancelled())
with:
- go-version: '^1.x'
- - uses: actions/cache@v4
- id: cache
+ files: ${{ steps.bazel_info.outputs.bazel-testlogs }}/**/test.xml
+ - uses: codecov/codecov-action@v6
+ if: (!cancelled())
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
- path: ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
- restore-keys: |
- ${{ runner.os }}-go-
- - name: install deps
- if: steps.cache.output.cache-hit != 'true'
- run: make --debug install_deps
- - name: local fuzz regtest
- run: make --debug CXX=clang LIB_FUZZING_ENGINE=-fsanitize=fuzzer fuzz-regtest
+ files: ${{ steps.bazel_info.outputs.output_path }}/_coverage/_coverage_report.dat
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
deleted file mode 100644
index 55cd60225..000000000
--- a/.github/workflows/codeql-analysis.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-# For most projects, this workflow file will not need changing; you simply need
-# to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-#
-name: "CodeQL"
-
-on:
- push:
- branches: [ main ]
- pull_request:
- # The branches below must be a subset of the branches above
- branches: [ main ]
- schedule:
- - cron: '34 6 * * 3'
-
-permissions:
- # https://github.com/github/codeql-action/issues/464
- security-events: write
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: false
- matrix:
- language: [ 'go' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
- # Learn more:
- # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v3
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v3
-
- # βΉοΈ Command-line programs to run using the OS shell.
- # π https://git.io/JvXDl
-
- # βοΈ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- #- run: |
- # make bootstrap
- # make release
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
deleted file mode 100644
index 274e98a2f..000000000
--- a/.github/workflows/golangci-lint.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-name: golangci-lint
-on:
- push:
- tags:
- - v*
- branches:
- - main
- pull_request:
-
-jobs:
- golangci:
- name: lint
- runs-on: ubuntu-latest
- permissions:
- # contents required to read the change
- contents: read
- # allow read access to any pull request
- pull-requests: read
- # golangci-lint does annotations, not comments, which needs `checks` to annotate the code.
- # These are hidden in the code, and not visible as comments in the PR.
- # https://github.com/golangci/golangci-lint-action/issues/5
- # No-one knows what an annotation is, but I suspect it's printing file:line: msg to stdout.
- # https://github.community/t/what-are-annotations/16173/2
- checks: write
- steps:
- - uses: actions/checkout@v4
- - uses: golangci/golangci-lint-action@v6
- with:
- # Required: the version of golangci-lint is required and must be
- # specified without patch version: we always use the latest patch
- # version.
- version: v1.59
- only-new-issues: ${{ github.event_name == 'pull_request' }}
diff --git a/.github/workflows/oss-fuzz.yml b/.github/workflows/oss-fuzz.yml
index dab46e78e..1de88eeef 100644
--- a/.github/workflows/oss-fuzz.yml
+++ b/.github/workflows/oss-fuzz.yml
@@ -27,7 +27,7 @@ jobs:
oss-fuzz-project-name: 'mtail'
dry-run: false
- name: Upload Crash
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0c21e6ce3..68d8611e6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -4,10 +4,11 @@ on:
# goreleaser is put into snapshot mode when not on a tag
pull_request:
merge_group:
- # Run when a tag is pushed.
- push:
- tags:
- - v*
+ push: # testing, unless there's a tag (steps.0.if below)
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
env:
REGISTRY: ghcr.io
@@ -26,22 +27,26 @@ jobs:
binary_hashes: ${{ steps.binary.outputs.hashes }}
image_subjects: ${{ steps.image.outputs.subjects }}
steps:
+ - name: print github context
+ env:
+ GITHUB_CONTEXT: ${{ toJSON(github) }}
+ run: echo $GITHUB_CONTEXT
- if: ${{ !startsWith(github.ref, 'refs/tags/') }}
run: echo "flags=--snapshot" >> $GITHUB_ENV
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
fetch-depth: 0
- run: git fetch --force --tags
- - uses: actions/setup-go@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
cache: true
- - uses: docker/login-action@v3.3.0
+ - uses: docker/login-action@v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - uses: goreleaser/goreleaser-action@v6
+ - uses: goreleaser/goreleaser-action@v7
id: goreleaser
with:
version: latest
@@ -72,7 +77,7 @@ jobs:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: "${{ needs.goreleaser.outputs.binary_hashes }}"
upload-assets: true # upload to a new release
@@ -84,7 +89,7 @@ jobs:
permissions:
contents: read
steps:
- - uses: slsa-framework/slsa-verifier/actions/installer@v2.6.0
+ - uses: slsa-framework/slsa-verifier/actions/installer@v2.7.1
- name: download assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -115,7 +120,7 @@ jobs:
packages: write
strategy:
matrix: ${{ fromJSON(needs.goreleaser.outputs.image_subjects) }}
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
with:
image: ghcr.io/${{ matrix.image }}
digest: ${{ matrix.digest }}
@@ -132,12 +137,12 @@ jobs:
strategy:
matrix: ${{ fromJSON(needs.goreleaser.outputs.image_subjects) }}
steps:
- - uses: docker/login-action@v3.3.0
+ - uses: docker/login-action@v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - uses: sigstore/cosign-installer@v3.7.0
+ - uses: sigstore/cosign-installer@v4.1.2
- name: verify image
env:
IMAGE: ${{ matrix.image }}
diff --git a/.github/workflows/remove-old-package-versions.yml b/.github/workflows/remove-old-package-versions.yml
index afda8e516..6bd06e870 100644
--- a/.github/workflows/remove-old-package-versions.yml
+++ b/.github/workflows/remove-old-package-versions.yml
@@ -14,4 +14,4 @@ jobs:
with:
package-name: mtail
package-type: container
- min-versions-to-keep: 10
+ min-versions-to-keep: 50
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index a80f5fc87..30f4ccf96 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -11,7 +11,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v9
+ - uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue has been waiting for more information for more than 60 days and will be closed in 7 if no update is provided.'
diff --git a/.github/workflows/tag-new-release.yml b/.github/workflows/tag-new-release.yml
index f945089a1..9514d7a28 100644
--- a/.github/workflows/tag-new-release.yml
+++ b/.github/workflows/tag-new-release.yml
@@ -1,21 +1,24 @@
name: tag new release
on:
+ push: # for testing
pull_request: # for testing
- workflow_dispatch:
+ workflow_dispatch: # manual invocation
schedule:
- cron: "30 5 * * 0"
jobs:
tag:
runs-on: ubuntu-latest
+ permissions:
+ contents: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- uses: mathieudutour/github-tag-action@v6.2
continue-on-error: true # ok to not make a new tag
with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
+ # Special PAT so that we trigger new workflows, that has contents:write only
+ github_token: ${{ secrets.TAG_TOKEN }}
create_annotated_tag: true
custom_release_rules: ci:none,chore:none,style:none
- default_bump: none
dry_run: ${{ github.event_name != 'workflow_dispatch' && github.event_name != 'schedule' }}
diff --git a/.gitignore b/.gitignore
index 06af14347..4350c0320 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,6 @@ foo.log
/.*dep-stamp
/cpu.out
/mem.out
-/build
/.ghi.yml
/vm-fuzz.zip
workdir/*
@@ -46,3 +45,7 @@ workdir/*
/fuzzer.h
/dist/
/main.*.go
+/bazel-bin
+/bazel-mtail
+/bazel-out
+/bazel-testlogs
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b3d3a12cc..3fae39195 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,8 +7,8 @@ stages:
before_script:
- mkdir ${CI_PROJECT_DIR}/build
- mkdir -p ${GOPATH}/src/github.com/google/
- - ln -s $(pwd) ${GOPATH}/src/github.com/google/mtail
- - cd ${GOPATH}/src/github.com/google/mtail
+ - ln -s $(pwd) ${GOPATH}/src/github.com/jaqx0r/mtail
+ - cd ${GOPATH}/src/github.com/jaqx0r/mtail
test:
stage: test
diff --git a/.golangci.yml b/.golangci.yml
index 5a29f3bf6..251b36903 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -27,8 +27,6 @@ linters:
- test
- unused
- metalinter
- enable:
- - exportloopref
# A general rule is if the lint author can't be bothered supplying automated
# fixes for obvious lint warnings, I'm not bothered using their tool.
disable:
@@ -47,7 +45,6 @@ linters:
- gocognit # boo cyclomatic complexity
- gocyclo # boo cyclomatic complexity
- godox # TODOs are fine
- - gomnd # magic numbers in test tables are fine actually
- gosec # run independently
- lll # go says long lines are ok, and this is trivially automatable
- musttag # don't agree with the premise
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 0d54cadc2..9a4506deb 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -1,6 +1,9 @@
+version: 2
before:
hooks:
- go mod download
+ - go install golang.org/x/tools/cmd/goyacc
+ - go generate ./...
builds:
- id: mtail
main: ./cmd/mtail/main.go
@@ -21,7 +24,7 @@ builds:
checksum:
name_template: 'checksums.txt'
snapshot:
- name_template: "{{ .Tag }}-next"
+ version_template: "{{ .Tag }}-next"
changelog:
filters:
exclude:
@@ -31,47 +34,45 @@ release:
github:
name_template: v{{.Version}}
dockers:
-- image_templates: ["ghcr.io/google/{{ .ProjectName }}:{{ .Version }}-amd64"]
+- image_templates: ["ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}-amd64"]
dockerfile: Dockerfile.goreleaser
use: buildx
build_flag_templates:
- --platform=linux/amd64
- - --label=org.opencontainers.image.ref.name="google/mtail"
+ - --label=org.opencontainers.image.ref.name="jaqx0r/mtail"
- --label=org.opencontainers.image.authors="Jamie Wilkinson (@jaqx0r)"
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.description="extract internal monitoring data from application logs for collection in a timeseries database"
- - --label=org.opencontainers.image.documentation="https://google.github.io/mtail/"
+ - --label=org.opencontainers.image.documentation="https://jaqx0r.github.io/mtail/"
- --label=org.opencontainers.image.licenses="Apache-2.0"
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- - --label=org.opencontainers.image.source=https://github.com/google/{{ .ProjectName }}
+ - --label=org.opencontainers.image.source=https://github.com/jaqx0r/{{ .ProjectName }}
- --label=org.opencontainers.image.title={{ .ProjectName }}
- - --label=org.opencontainers.image.url=https://github.com/google/{{ .ProjectName }}
- - --label=org.opencontainers.image.vendor="Google"
+ - --label=org.opencontainers.image.url=https://github.com/jaqx0r/{{ .ProjectName }}
- --label=org.opencontainers.image.version={{ .Version }}
-- image_templates: ["ghcr.io/google/{{ .ProjectName }}:{{ .Version }}-arm64v8"]
+- image_templates: ["ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}-arm64v8"]
goarch: arm64
dockerfile: Dockerfile.goreleaser
use: buildx
build_flag_templates:
- --platform=linux/arm64/v8
- - --label=org.opencontainers.image.ref.name="google/mtail"
+ - --label=org.opencontainers.image.ref.name="jaqx0r/mtail"
- --label=org.opencontainers.image.authors="Jamie Wilkinson (@jaqx0r)"
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.description="extract internal monitoring data from application logs for collection in a timeseries database"
- - --label=org.opencontainers.image.documentation="https://google.github.io/mtail/"
+ - --label=org.opencontainers.image.documentation="https://jaqx0r.github.io/mtail/"
- --label=org.opencontainers.image.licenses="Apache-2.0"
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- - --label=org.opencontainers.image.source=https://github.com/google/{{ .ProjectName }}
+ - --label=org.opencontainers.image.source=https://github.com/jaqx0r/{{ .ProjectName }}
- --label=org.opencontainers.image.title={{ .ProjectName }}
- - --label=org.opencontainers.image.url=https://github.com/google/{{ .ProjectName }}
- - --label=org.opencontainers.image.vendor="Google"
+ - --label=org.opencontainers.image.url=https://github.com/jaqx0r/{{ .ProjectName }}
- --label=org.opencontainers.image.version={{ .Version }}
docker_manifests:
- - name_template: ghcr.io/google/{{ .ProjectName }}:{{ .Version }}
+ - name_template: ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}
image_templates:
- - ghcr.io/google/{{ .ProjectName }}:{{ .Version }}-amd64
- - ghcr.io/google/{{ .ProjectName }}:{{ .Version }}-arm64v8
- - name_template: ghcr.io/google/{{ .ProjectName }}:latest
+ - ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}-amd64
+ - ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}-arm64v8
+ - name_template: ghcr.io/jaqx0r/{{ .ProjectName }}:latest
image_templates:
- - ghcr.io/google/{{ .ProjectName }}:{{ .Version }}-amd64
- - ghcr.io/google/{{ .ProjectName }}:{{ .Version }}-arm64v8
+ - ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}-amd64
+ - ghcr.io/jaqx0r/{{ .ProjectName }}:{{ .Version }}-arm64v8
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..cc0b801b9
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,23 @@
+# mtail agent guide
+
+## Build & test
+
+- **Only Bazel** β all development iteration uses `bazel test //...`.
+- **Always `gofmt` your code** before submitting.
+
+## Project structure
+
+- `cmd/{mtail,mdot,mgen,mfmt}/main.go` β four binaries: `mtail` and `mfmt` are the ones that matter.
+- `internal/` β core packages: `logline`, `metrics`, `runtime` (compiler + vm), `tailer`, `exporter`, `testutil`.
+- `internal/testutil/` β shared test helpers.
+- `examples/*.mtail` β sample mtail programs, also used as test fixtures.
+
+## Documentation
+
+- `docs` has extensive instructions for users and developers, written in Markdown. Keep these up to date.
+
+## Testing conventions
+
+- Table-driven tests with `t.Run` subtest form.
+- Comparison: `deep.Equal(expected, observed)` from `github.com/google/go-cmp`. Order is always expected first.
+- `testutil` package provides common helpers (e.g., `testutil.TestServer`).
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 000000000..c3eb0ecab
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,20 @@
+load("@gazelle//:def.bzl", "gazelle")
+load("@rules_go//go:def.bzl", "nogo")
+
+# gazelle:prefix github.com/jaqx0r/mtail
+gazelle(name = "gazelle")
+
+nogo(
+ name = "nogo",
+ vet = True,
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
+ name = "docs",
+ srcs = [
+ "LICENSE",
+ "README.md",
+ ],
+ visibility = ["//release:__pkg__"],
+)
diff --git a/Dockerfile b/Dockerfile
index 2798d5e9c..482f7bb52 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
FROM golang:alpine AS builder
RUN apk add --update git make
-WORKDIR /go/src/github.com/google/mtail
-COPY . /go/src/github.com/google/mtail
+WORKDIR /go/src/github.com/jaqx0r/mtail
+COPY . /go/src/github.com/jaqx0r/mtail
RUN make depclean && make install_deps && PREFIX=/go make STATIC=y -B install
@@ -18,8 +18,7 @@ ARG commit_hash=unknown
ARG vcs_url=unknown
ARG vcs_branch=unknown
-LABEL org.opencontainers.image.ref.name="google/mtail" \
- org.opencontainers.image.vendor="Google" \
+LABEL org.opencontainers.image.ref.name="jaqx0r/mtail" \
org.opencontainers.image.title="mtail" \
org.opencontainers.image.description="extract internal monitoring data from application logs for collection in a timeseries database" \
org.opencontainers.image.authors="Jamie Wilkinson (@jaqx0r)" \
@@ -29,4 +28,4 @@ LABEL org.opencontainers.image.ref.name="google/mtail" \
org.opencontainers.image.source=$vcs_url \
org.opencontainers.image.documentation="https://google.github.io/mtail/" \
org.opencontainers.image.created=$build_date \
- org.opencontainers.image.url="https://github.com/google/mtail"
+ org.opencontainers.image.url="https://github.com/jaqx0r/mtail"
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index dd8bdacf6..df6e611ca 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -6,7 +6,7 @@ If your problem is with the way an `mtail` program is behaving, please attach or
If your problem is with `mtail`, please include the commandline you started it with, and the INFO log.
-See also [Reporting a problem](https://github.com/google/mtail/blob/main/docs/Troubleshooting.md#reporting-a-problem).
+See also [Reporting a problem](https://github.com/jaqx0r/mtail/blob/main/docs/Troubleshooting.md#reporting-a-problem).
Thanks!
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 000000000..f8669a27b
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,56 @@
+module(
+ name = "mtail",
+ version = "3",
+)
+
+bazel_dep(name = "rules_go", version = "0.60.0")
+
+go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
+go_sdk.from_file(go_mod = "//:go.mod")
+
+# https://github.com/bazel-contrib/rules_go/blob/master/go/nogo.rst
+# Like golangci-lint, but integrated into the build.
+go_sdk.nogo(nogo = "//:nogo")
+
+bazel_dep(name = "gazelle", version = "0.51.1")
+
+# Update dependencies with
+# `bazel run //:gazelle`.
+# and then
+# `bazel run @rules_go//go -- mod tidy`
+go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
+go_deps.from_file(go_mod = "//:go.mod")
+use_repo(
+ go_deps,
+ "com_github_golang_glog",
+ "com_github_golang_groupcache",
+ "com_github_google_go_cmp",
+ "com_github_pkg_errors",
+ "com_github_prometheus_client_golang",
+ "com_github_prometheus_common",
+ "io_opencensus_go",
+ "io_opencensus_go_contrib_exporter_jaeger",
+ "io_opentelemetry_go_otel",
+ "io_opentelemetry_go_otel_exporters_otlp_otlpmetric_otlpmetricgrpc",
+ "io_opentelemetry_go_otel_sdk",
+ "io_opentelemetry_go_otel_sdk_metric",
+ "org_golang_x_sys",
+ "org_golang_x_tools",
+)
+
+bazel_dep(name = "aspect_bazel_lib", version = "2.22.5")
+bazel_dep(name = "rules_img", version = "0.3.11")
+bazel_dep(name = "platforms", version = "1.1.0")
+
+pull = use_repo_rule("@rules_img//img:pull.bzl", "pull")
+
+pull(
+ name = "distroless_base",
+ digest = "sha256:f2df8702d4dcc45ce76df6cbc14ad1975fcf88a04bd0e8947b6194264f9ab75e",
+ layer_handling = "lazy",
+ registry = "gcr.io",
+ repository = "distroless/base",
+)
+
+# `rules_pkg` for making releases
+bazel_dep(name = "rules_pkg", version = "1.2.0")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
new file mode 100644
index 000000000..a1cd27f7a
--- /dev/null
+++ b/MODULE.bazel.lock
@@ -0,0 +1,910 @@
+{
+ "lockFileVersion": 26,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c",
+ "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
+ "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
+ "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e",
+ "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1",
+ "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4",
+ "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/2.14.0/MODULE.bazel": "2b31ffcc9bdc8295b2167e07a757dbbc9ac8906e7028e5170a3708cecaac119f",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/2.19.3/MODULE.bazel": "253d739ba126f62a5767d832765b12b59e9f8d2bc88cc1572f4a73e46eb298ca",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.5/MODULE.bazel": "004ba890363d05372a97248c37205ae64b6fa31047629cd2c0895a9d0c7779e8",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/2.22.5/source.json": "ac2c3213df8f985785f1d0aeb7f0f73d5324e6e67d593d9b9470fb74a25d4a9b",
+ "https://bcr.bazel.build/modules/aspect_bazel_lib/2.8.1/MODULE.bazel": "812d2dd42f65dca362152101fbec418029cc8fd34cbad1a2fde905383d705838",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a",
+ "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
+ "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
+ "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
+ "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
+ "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
+ "https://bcr.bazel.build/modules/bazel_features/1.36.0/MODULE.bazel": "596cb62090b039caf1cad1d52a8bc35cf188ca9a4e279a828005e7ee49a1bec3",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080",
+ "https://bcr.bazel.build/modules/bazel_features/1.46.0/MODULE.bazel": "3371af60ed64c67aa05401c08005e6b0418433b2a18712994e17300f0a610b2a",
+ "https://bcr.bazel.build/modules/bazel_features/1.47.0/MODULE.bazel": "e34df3cb35b1684cfa69923a61ae3803595babd3942cd306a488d51400886b30",
+ "https://bcr.bazel.build/modules/bazel_features/1.47.0/source.json": "4ba0b5138327f2d73352a51547a4e49a0a828ef400e046b15334d8905bf6b7ff",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_lib/3.0.0/MODULE.bazel": "22b70b80ac89ad3f3772526cd9feee2fa412c2b01933fea7ed13238a448d370d",
+ "https://bcr.bazel.build/modules/bazel_lib/3.0.0/source.json": "895f21909c6fba01d7c17914bb6c8e135982275a1b18cdaa4e62272217ef1751",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/MODULE.bazel": "72997b29dfd95c3fa0d0c48322d05590418edef451f8db8db5509c57875fb4b7",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/source.json": "7ad77c1e8c1b84222d9b3f3cae016a76639435744c19330b0b37c0a3c9da7dc0",
+ "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f",
+ "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd",
+ "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/MODULE.bazel": "cdf8cbe5ee750db04b78878c9633cc76e80dcf4416cbe982ac3a9222f80713c8",
+ "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/source.json": "fa7b512dfcb5eafd90ce3959cf42a2a6fe96144ebbb4b3b3928054895f2afac2",
+ "https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8",
+ "https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350",
+ "https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a",
+ "https://bcr.bazel.build/modules/gazelle/0.36.0/MODULE.bazel": "e375d5d6e9a6ca59b0cb38b0540bc9a05b6aa926d322f2de268ad267a2ee74c0",
+ "https://bcr.bazel.build/modules/gazelle/0.51.0/MODULE.bazel": "74610189cc04e27cc2cc286eaffb98c9b43fe59fdf2980b086922eea79f4a236",
+ "https://bcr.bazel.build/modules/gazelle/0.51.0/source.json": "d69adfa4f68bbdce6a93a4a4b518cb4ee2fd5051366e4a33d3b7b42d749d0ae1",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
+ "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
+ "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713",
+ "https://bcr.bazel.build/modules/hermetic_launcher/0.0.5/MODULE.bazel": "0e00b51788823b75b4273aedbc6ba21f64dad453f7567f9359a2e96eb6ec101c",
+ "https://bcr.bazel.build/modules/hermetic_launcher/0.0.5/source.json": "eb5cf0f29fb36c10c2fde8f660cf5edfd377d8ea167f277fff9a811fd0a26028",
+ "https://bcr.bazel.build/modules/jq.bzl/0.1.0/MODULE.bazel": "2ce69b1af49952cd4121a9c3055faa679e748ce774c7f1fda9657f936cae902f",
+ "https://bcr.bazel.build/modules/jq.bzl/0.1.0/source.json": "746bf13cac0860f091df5e4911d0c593971cd8796b5ad4e809b2f8e133eee3d5",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
+ "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
+ "https://bcr.bazel.build/modules/package_metadata/0.0.10/MODULE.bazel": "cb66e0ce830e01bc00cd9edc984963704f2759ca893a649996e2b1c5c1ea7271",
+ "https://bcr.bazel.build/modules/package_metadata/0.0.10/source.json": "8fc6bece244828a69b3cc608f381118d67fa3cc2aa1a2851dfe8d99a8076d7d0",
+ "https://bcr.bazel.build/modules/package_metadata/0.0.2/MODULE.bazel": "fb8d25550742674d63d7b250063d4580ca530499f045d70748b1b142081ebb92",
+ "https://bcr.bazel.build/modules/package_metadata/0.0.3/MODULE.bazel": "77890552ecea9e284b5424c9de827a58099348763a4359e975c359a83d4faa83",
+ "https://bcr.bazel.build/modules/package_metadata/0.0.5/MODULE.bazel": "ef4f9439e3270fdd6b9fd4dbc3d2f29d13888e44c529a1b243f7a31dfbc2e8e4",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
+ "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
+ "https://bcr.bazel.build/modules/platforms/1.1.0/MODULE.bazel": "1c0c09f5bdcf4b3f924720d2478a3711cb39f4977019ca5988685e5b7e18b3d2",
+ "https://bcr.bazel.build/modules/platforms/1.1.0/source.json": "fcf351c47596c939140ab0d333dfdd08ed1ea6ce33c2fe70c12493a301cf1344",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2.bcr.1/MODULE.bazel": "52f4126f63a2f0bbf36b99c2a87648f08467a4eaf92ba726bc7d6a500bbf770c",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+ "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
+ "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573",
+ "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
+ "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d",
+ "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42",
+ "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
+ "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4",
+ "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
+ "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68",
+ "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_go/0.41.0/MODULE.bazel": "55861d8e8bb0e62cbd2896f60ff303f62ffcb0eddb74ecb0e5c0cbe36fc292c8",
+ "https://bcr.bazel.build/modules/rules_go/0.42.0/MODULE.bazel": "8cfa875b9aa8c6fce2b2e5925e73c1388173ea3c32a0db4d2b4804b453c14270",
+ "https://bcr.bazel.build/modules/rules_go/0.46.0/MODULE.bazel": "3477df8bdcc49e698b9d25f734c4f3a9f5931ff34ee48a2c662be168f5f2d3fd",
+ "https://bcr.bazel.build/modules/rules_go/0.59.0/MODULE.bazel": "b7e43e7414a3139a7547d1b4909b29085fbe5182b6c58cbe1ed4c6272815aeae",
+ "https://bcr.bazel.build/modules/rules_go/0.60.0/MODULE.bazel": "4a57ff2ffc2a3570e3c5646575c5a4b07287e91bcdac5d1f72383d51502b48cb",
+ "https://bcr.bazel.build/modules/rules_go/0.60.0/source.json": "1e21368c5e0c3013a110bd79a8fcff8ca46b5bcb2b561713a7273cbfcff7c464",
+ "https://bcr.bazel.build/modules/rules_img/0.3.11/MODULE.bazel": "85b9d7e2c5d83a321766dbc382c613c2399db680174bdfa32966f477989ee361",
+ "https://bcr.bazel.build/modules/rules_img/0.3.11/source.json": "fbde1bc544519df0fe254fa5c1be3b6189d44f548af3ee131935215ea6e8d078",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
+ "https://bcr.bazel.build/modules/rules_java/6.3.0/MODULE.bazel": "a97c7678c19f236a956ad260d59c86e10a463badb7eb2eda787490f4c969b963",
+ "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+ "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
+ "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d",
+ "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.2.0/MODULE.bazel": "c7db3c2b407e673c7a39e3625dc05dc9f12d6682cbd82a3a5924a13b491eda7e",
+ "https://bcr.bazel.build/modules/rules_pkg/1.2.0/source.json": "9062e00845bf91a4247465d371baa837adf9b6ff44c542f73ba084f07667e1dc",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+ "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96",
+ "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
+ "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6",
+ "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
+ "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8",
+ "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32",
+ "https://bcr.bazel.build/modules/rules_runfiles_group/0.0.1-rc.5/MODULE.bazel": "8e124a40a5a00e7ae8a103e2bdfea636392bc4ae7a26f416a07dfc41f3216cc9",
+ "https://bcr.bazel.build/modules/rules_runfiles_group/0.0.1-rc.5/source.json": "32efc01a4b29cbb5b2b97fd1f7d6025e68eb20eea498f1127b068082e315d6cf",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
+ "https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592",
+ "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
+ "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
+ "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
+ "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
+ "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd",
+ "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400",
+ "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
+ "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
+ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f",
+ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b",
+ "https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468",
+ "https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351",
+ "https://bcr.bazel.build/modules/tar.bzl/0.5.1/source.json": "deed3094f7cc779ed1d37a68403847b0e38d9dd9d931e03cb90825f3368b515f",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072",
+ "https://bcr.bazel.build/modules/yq.bzl/0.1.1/source.json": "2d2bad780a9f2b9195a4a370314d2c17ae95eaa745cefc2e12fbc49759b15aa3",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {
+ "@@pybind11_bazel+//:internal_configure.bzl%internal_configure_extension": {
+ "general": {
+ "bzlTransitiveDigest": "06cynZ1bCvvy8zHPrrDlXq+Z68xmjctHpfFxi+zEpJY=",
+ "usagesDigest": "D1r3lfzMuUBFxgG8V6o0bQTLMk3GkaGOaPzw53wrwyw=",
+ "recordedInputs": [
+ "REPO_MAPPING:pybind11_bazel+,bazel_tools bazel_tools",
+ "FILE:@@pybind11_bazel+//MODULE.bazel e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34"
+ ],
+ "generatedRepoSpecs": {
+ "pybind11": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "build_file": "@@pybind11_bazel+//:pybind11-BUILD.bazel",
+ "strip_prefix": "pybind11-2.12.0",
+ "urls": [
+ "https://github.com/pybind/pybind11/archive/v2.12.0.zip"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+ "general": {
+ "bzlTransitiveDigest": "Ga4z8lQy1YQ5rAMy+dOl0dqcCEBnYNCXku8x3YQmDZI=",
+ "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
+ "recordedInputs": [
+ "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools"
+ ],
+ "generatedRepoSpecs": {
+ "com_github_jetbrains_kotlin_git": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
+ ],
+ "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
+ }
+ },
+ "com_github_jetbrains_kotlin": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
+ "attributes": {
+ "git_repository_name": "com_github_jetbrains_kotlin_git",
+ "compiler_version": "1.9.23"
+ }
+ },
+ "com_github_google_ksp": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
+ ],
+ "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
+ "strip_version": "1.9.23-1.0.20"
+ }
+ },
+ "com_github_pinterest_ktlint": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
+ "attributes": {
+ "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
+ "urls": [
+ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
+ ],
+ "executable": true
+ }
+ },
+ "rules_android": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
+ "strip_prefix": "rules_android-0.1.1",
+ "urls": [
+ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "@@rules_python+//python/extensions:config.bzl%config": {
+ "general": {
+ "bzlTransitiveDigest": "iibnRYgg8LpcfmH7EAnVwYePC3jsVaJ6Id8XxUjSZps=",
+ "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=",
+ "recordedInputs": [
+ "REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
+ "REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build",
+ "REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click",
+ "REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama",
+ "REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata",
+ "REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer",
+ "REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools",
+ "REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging",
+ "REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517",
+ "REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip",
+ "REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools",
+ "REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks",
+ "REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools",
+ "REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli",
+ "REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel",
+ "REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp"
+ ],
+ "generatedRepoSpecs": {
+ "rules_python_internal": {
+ "repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo",
+ "attributes": {
+ "transition_setting_generators": {},
+ "transition_settings": []
+ }
+ },
+ "pypi__build": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl",
+ "sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__click": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl",
+ "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__colorama": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl",
+ "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__importlib_metadata": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl",
+ "sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__installer": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl",
+ "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__more_itertools": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl",
+ "sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__packaging": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl",
+ "sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__pep517": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl",
+ "sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__pip": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl",
+ "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__pip_tools": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl",
+ "sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__pyproject_hooks": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl",
+ "sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__setuptools": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl",
+ "sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__tomli": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl",
+ "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__wheel": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl",
+ "sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ },
+ "pypi__zipp": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl",
+ "sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e",
+ "type": "zip",
+ "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
+ }
+ }
+ }
+ }
+ },
+ "@@rules_python+//python/uv:uv.bzl%uv": {
+ "general": {
+ "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=",
+ "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=",
+ "recordedInputs": [
+ "REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
+ "REPO_MAPPING:rules_python+,platforms platforms"
+ ],
+ "generatedRepoSpecs": {
+ "uv": {
+ "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
+ "attributes": {
+ "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
+ "toolchain_names": [
+ "none"
+ ],
+ "toolchain_implementations": {
+ "none": "'@@rules_python+//python:none'"
+ },
+ "toolchain_compatible_with": {
+ "none": [
+ "@platforms//:incompatible"
+ ]
+ },
+ "toolchain_target_settings": {}
+ }
+ }
+ }
+ }
+ },
+ "@@tar.bzl+//tar:extensions.bzl%toolchains": {
+ "general": {
+ "bzlTransitiveDigest": "/2afh6fPjq/rcyE/jztQDK3ierehmFFngfvmqyRv72M=",
+ "usagesDigest": "maF8qsAIqeH1ey8pxP0gNZbvJt34kLZvTFeQ0ntrJVA=",
+ "recordedInputs": [],
+ "generatedRepoSpecs": {
+ "bsd_tar_toolchains": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:toolchain.bzl%tar_toolchains_repo",
+ "attributes": {
+ "user_repository_name": "bsd_tar_toolchains"
+ }
+ },
+ "bsd_tar_toolchains_darwin_amd64": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:platforms.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_amd64"
+ }
+ },
+ "bsd_tar_toolchains_darwin_arm64": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:platforms.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "darwin_arm64"
+ }
+ },
+ "bsd_tar_toolchains_linux_amd64": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:platforms.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_amd64"
+ }
+ },
+ "bsd_tar_toolchains_linux_arm64": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:platforms.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "linux_arm64"
+ }
+ },
+ "bsd_tar_toolchains_windows_amd64": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:platforms.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "windows_amd64"
+ }
+ },
+ "bsd_tar_toolchains_windows_arm64": {
+ "repoRuleId": "@@tar.bzl+//tar/toolchain:platforms.bzl%bsdtar_binary_repo",
+ "attributes": {
+ "platform": "windows_arm64"
+ }
+ }
+ }
+ }
+ }
+ },
+ "facts": {
+ "@@rules_go+//go:extensions.bzl%go_sdk": {
+ "1.25.0": {
+ "aix_ppc64": [
+ "go1.25.0.aix-ppc64.tar.gz",
+ "e5234a7dac67bc86c528fe9752fc9d63557918627707a733ab4cac1a6faed2d4"
+ ],
+ "darwin_amd64": [
+ "go1.25.0.darwin-amd64.tar.gz",
+ "5bd60e823037062c2307c71e8111809865116714d6f6b410597cf5075dfd80ef"
+ ],
+ "darwin_arm64": [
+ "go1.25.0.darwin-arm64.tar.gz",
+ "544932844156d8172f7a28f77f2ac9c15a23046698b6243f633b0a0b00c0749c"
+ ],
+ "dragonfly_amd64": [
+ "go1.25.0.dragonfly-amd64.tar.gz",
+ "5ed3cf9a810a1483822538674f1336c06b51aa1b94d6d545a1a0319a48177120"
+ ],
+ "freebsd_386": [
+ "go1.25.0.freebsd-386.tar.gz",
+ "abea5d5c6697e6b5c224731f2158fe87c602996a2a233ac0c4730cd57bf8374e"
+ ],
+ "freebsd_amd64": [
+ "go1.25.0.freebsd-amd64.tar.gz",
+ "86e6fe0a29698d7601c4442052dac48bd58d532c51cccb8f1917df648138730b"
+ ],
+ "freebsd_arm": [
+ "go1.25.0.freebsd-arm.tar.gz",
+ "d90b78e41921f72f30e8bbc81d9dec2cff7ff384a33d8d8debb24053e4336bfe"
+ ],
+ "freebsd_arm64": [
+ "go1.25.0.freebsd-arm64.tar.gz",
+ "451d0da1affd886bfb291b7c63a6018527b269505db21ce6e14724f22ab0662e"
+ ],
+ "freebsd_riscv64": [
+ "go1.25.0.freebsd-riscv64.tar.gz",
+ "7b565f76bd8bda46549eeaaefe0e53b251e644c230577290c0f66b1ecdb3cdbe"
+ ],
+ "illumos_amd64": [
+ "go1.25.0.illumos-amd64.tar.gz",
+ "b1e1fdaab1ad25aa1c08d7a36c97d45d74b98b89c3f78c6d2145f77face54a2c"
+ ],
+ "linux_386": [
+ "go1.25.0.linux-386.tar.gz",
+ "8c602dd9d99bc9453b3995d20ce4baf382cc50855900a0ece5de9929df4a993a"
+ ],
+ "linux_amd64": [
+ "go1.25.0.linux-amd64.tar.gz",
+ "2852af0cb20a13139b3448992e69b868e50ed0f8a1e5940ee1de9e19a123b613"
+ ],
+ "linux_arm64": [
+ "go1.25.0.linux-arm64.tar.gz",
+ "05de75d6994a2783699815ee553bd5a9327d8b79991de36e38b66862782f54ae"
+ ],
+ "linux_armv6l": [
+ "go1.25.0.linux-armv6l.tar.gz",
+ "a5a8f8198fcf00e1e485b8ecef9ee020778bf32a408a4e8873371bfce458cd09"
+ ],
+ "linux_loong64": [
+ "go1.25.0.linux-loong64.tar.gz",
+ "cab86b1cf761b1cb3bac86a8877cfc92e7b036fc0d3084123d77013d61432afc"
+ ],
+ "linux_mips": [
+ "go1.25.0.linux-mips.tar.gz",
+ "d66b6fb74c3d91b9829dc95ec10ca1f047ef5e89332152f92e136cf0e2da5be1"
+ ],
+ "linux_mips64": [
+ "go1.25.0.linux-mips64.tar.gz",
+ "4082e4381a8661bc2a839ff94ba3daf4f6cde20f8fb771b5b3d4762dc84198a2"
+ ],
+ "linux_mips64le": [
+ "go1.25.0.linux-mips64le.tar.gz",
+ "70002c299ec7f7175ac2ef673b1b347eecfa54ae11f34416a6053c17f855afcc"
+ ],
+ "linux_mipsle": [
+ "go1.25.0.linux-mipsle.tar.gz",
+ "b00a3a39eff099f6df9f1c7355bf28e4589d0586f42d7d4a394efb763d145a73"
+ ],
+ "linux_ppc64": [
+ "go1.25.0.linux-ppc64.tar.gz",
+ "df166f33bd98160662560a72ff0b4ba731f969a80f088922bddcf566a88c1ec1"
+ ],
+ "linux_ppc64le": [
+ "go1.25.0.linux-ppc64le.tar.gz",
+ "0f18a89e7576cf2c5fa0b487a1635d9bcbf843df5f110e9982c64df52a983ad0"
+ ],
+ "linux_riscv64": [
+ "go1.25.0.linux-riscv64.tar.gz",
+ "c018ff74a2c48d55c8ca9b07c8e24163558ffec8bea08b326d6336905d956b67"
+ ],
+ "linux_s390x": [
+ "go1.25.0.linux-s390x.tar.gz",
+ "34e5a2e19f2292fbaf8783e3a241e6e49689276aef6510a8060ea5ef54eee408"
+ ],
+ "netbsd_386": [
+ "go1.25.0.netbsd-386.tar.gz",
+ "f8586cdb7aa855657609a5c5f6dbf523efa00c2bbd7c76d3936bec80aa6c0aba"
+ ],
+ "netbsd_amd64": [
+ "go1.25.0.netbsd-amd64.tar.gz",
+ "ae8dc1469385b86a157a423bb56304ba45730de8a897615874f57dd096db2c2a"
+ ],
+ "netbsd_arm": [
+ "go1.25.0.netbsd-arm.tar.gz",
+ "1ff7e4cc764425fc9dd6825eaee79d02b3c7cafffbb3691687c8d672ade76cb7"
+ ],
+ "netbsd_arm64": [
+ "go1.25.0.netbsd-arm64.tar.gz",
+ "e1b310739f26724216aa6d7d7208c4031f9ff54c9b5b9a796ddc8bebcb4a5f16"
+ ],
+ "openbsd_386": [
+ "go1.25.0.openbsd-386.tar.gz",
+ "4802a9b20e533da91adb84aab42e94aa56cfe3e5475d0550bed3385b182e69d8"
+ ],
+ "openbsd_amd64": [
+ "go1.25.0.openbsd-amd64.tar.gz",
+ "c016cd984bebe317b19a4f297c4f50def120dc9788490540c89f28e42f1dabe1"
+ ],
+ "openbsd_arm": [
+ "go1.25.0.openbsd-arm.tar.gz",
+ "a1e31d0bf22172ddde42edf5ec811ef81be43433df0948ece52fecb247ccfd8d"
+ ],
+ "openbsd_arm64": [
+ "go1.25.0.openbsd-arm64.tar.gz",
+ "343ea8edd8c218196e15a859c6072d0dd3246fbbb168481ab665eb4c4140458d"
+ ],
+ "openbsd_ppc64": [
+ "go1.25.0.openbsd-ppc64.tar.gz",
+ "694c14da1bcaeb5e3332d49bdc2b6d155067648f8fe1540c5de8f3cf8e157154"
+ ],
+ "openbsd_riscv64": [
+ "go1.25.0.openbsd-riscv64.tar.gz",
+ "aa510ad25cf54c06cd9c70b6d80ded69cb20188ac6e1735655eef29ff7e7885f"
+ ],
+ "plan9_386": [
+ "go1.25.0.plan9-386.tar.gz",
+ "46f8cef02086cf04bf186c5912776b56535178d4cb319cd19c9fdbdd29231986"
+ ],
+ "plan9_amd64": [
+ "go1.25.0.plan9-amd64.tar.gz",
+ "29b34391d84095e44608a228f63f2f88113a37b74a79781353ec043dfbcb427b"
+ ],
+ "plan9_arm": [
+ "go1.25.0.plan9-arm.tar.gz",
+ "0a047107d13ebe7943aaa6d54b1d7bbd2e45e68ce449b52915a818da715799c2"
+ ],
+ "solaris_amd64": [
+ "go1.25.0.solaris-amd64.tar.gz",
+ "9977f9e4351984364a3b2b78f8b88bfd1d339812356d5237678514594b7d3611"
+ ],
+ "windows_386": [
+ "go1.25.0.windows-386.zip",
+ "df9f39db82a803af0db639e3613a36681ab7a42866b1384b3f3a1045663961a7"
+ ],
+ "windows_amd64": [
+ "go1.25.0.windows-amd64.zip",
+ "89efb4f9b30812eee083cc1770fdd2913c14d301064f6454851428f9707d190b"
+ ],
+ "windows_arm64": [
+ "go1.25.0.windows-arm64.zip",
+ "27bab004c72b3d7bd05a69b6ec0fc54a309b4b78cc569dd963d8b3ec28bfdb8c"
+ ]
+ },
+ "1.26.3": {
+ "aix_ppc64": [
+ "go1.26.3.aix-ppc64.tar.gz",
+ "9fd8b45c4aa58fa6adf7f347343a3b50c02b17a4b5c43381dd9bf87be563183d"
+ ],
+ "darwin_amd64": [
+ "go1.26.3.darwin-amd64.tar.gz",
+ "278d580b32e299fe4a9c990fcf2d02acfe538c7e551a6ee18f9c7164573d2c63"
+ ],
+ "darwin_arm64": [
+ "go1.26.3.darwin-arm64.tar.gz",
+ "875cf54a15311eee2c99b9dd67c68c4a49351d489ab622bf2cfd28c8f2078d3c"
+ ],
+ "dragonfly_amd64": [
+ "go1.26.3.dragonfly-amd64.tar.gz",
+ "6bfeaae407b12affd477cd48674e51d34931b6d98afc59de0f50ef93523ea4bf"
+ ],
+ "freebsd_386": [
+ "go1.26.3.freebsd-386.tar.gz",
+ "270df83863a4fbeb716565e91915f54af4ed911ec503651fbce6c14f9e00018c"
+ ],
+ "freebsd_amd64": [
+ "go1.26.3.freebsd-amd64.tar.gz",
+ "2a5a3b0265f24cdf3878bbab19bb1086f71ae5d29566f238214847d1e3745b4e"
+ ],
+ "freebsd_arm": [
+ "go1.26.3.freebsd-arm.tar.gz",
+ "db3700f0173ef7d15b96b4a2fa34c7fce90455e3125491183d751c9270b63d96"
+ ],
+ "freebsd_arm64": [
+ "go1.26.3.freebsd-arm64.tar.gz",
+ "07431d472522d3e3b9fce3f5d1ea825e2fbb14d7b0b7fbfa548726654217127c"
+ ],
+ "illumos_amd64": [
+ "go1.26.3.illumos-amd64.tar.gz",
+ "2c5bc6a2c7c43e09a91b19117fa18ce9012393a9f42fc0d153cad345fd328dad"
+ ],
+ "linux_386": [
+ "go1.26.3.linux-386.tar.gz",
+ "0ef3626a149b5811c813838c62b7d6618d03ea36047b32c90b0e4851cc42b1fa"
+ ],
+ "linux_amd64": [
+ "go1.26.3.linux-amd64.tar.gz",
+ "2b2cfc7148493da5e73981bffbf3353af381d5f93e789c82c79aff64962eb556"
+ ],
+ "linux_arm64": [
+ "go1.26.3.linux-arm64.tar.gz",
+ "9d89a3ea57d141c2b22d70083f2c8459ba3890f2d9e818e7e933b75614936565"
+ ],
+ "linux_armv6l": [
+ "go1.26.3.linux-armv6l.tar.gz",
+ "d44133d4c66b1451a1e247da26db7716f76a081c0169a75e6c84e1871e394320"
+ ],
+ "linux_loong64": [
+ "go1.26.3.linux-loong64.tar.gz",
+ "05215802b85a33dcfdb933a6c3ab881f4f0405587ee6581d33f34cc5c2ab740c"
+ ],
+ "linux_mips": [
+ "go1.26.3.linux-mips.tar.gz",
+ "76800ce7007d5eacabfe25d038e0a99e73a0fb70c4dd13f8a9662045fb4a52a7"
+ ],
+ "linux_mips64": [
+ "go1.26.3.linux-mips64.tar.gz",
+ "f2c755d17c6834dd3ae805d815a1b9e2eda66375de6ca910efb903a257ff3a3d"
+ ],
+ "linux_mips64le": [
+ "go1.26.3.linux-mips64le.tar.gz",
+ "54f7b00bf2d5cf4b21734cc8eb3c61c51a76177d3d20cd667e4b1ba8fb3343d5"
+ ],
+ "linux_mipsle": [
+ "go1.26.3.linux-mipsle.tar.gz",
+ "31f7d8c886136b725d36880f6ee16fe22a7243751839a2de2ea2da3cb4fd3fe1"
+ ],
+ "linux_ppc64": [
+ "go1.26.3.linux-ppc64.tar.gz",
+ "459746b1b06eb24836d1e4699c6568220c95e82de9b1b155c74eb4fdfd711532"
+ ],
+ "linux_ppc64le": [
+ "go1.26.3.linux-ppc64le.tar.gz",
+ "dbd82b50530ead2beb1fd72215117380df3cb16332b51467116dc35b3691dd75"
+ ],
+ "linux_riscv64": [
+ "go1.26.3.linux-riscv64.tar.gz",
+ "3b8fd5112340b72587e42c619f43270f1bc21f63cfdb587e6b72e0336580727c"
+ ],
+ "linux_s390x": [
+ "go1.26.3.linux-s390x.tar.gz",
+ "5c0605b7175449f1c8e8cb02efaba2695caab914fad4dcedc764c2f4c6dfe6ca"
+ ],
+ "netbsd_386": [
+ "go1.26.3.netbsd-386.tar.gz",
+ "15c74255bb23fe9690faac4e489c654cea35d5059a59744e0afd0f78a29a6e53"
+ ],
+ "netbsd_amd64": [
+ "go1.26.3.netbsd-amd64.tar.gz",
+ "a622ef5f3a6d42661ca75bdc939d8cb0468bb1a4418755b6d8c1b4acb82dd03c"
+ ],
+ "netbsd_arm": [
+ "go1.26.3.netbsd-arm.tar.gz",
+ "696df9d8562ac0118c3b8fd6578978d1c4e35583fe2d655e18b6520da7508ec9"
+ ],
+ "netbsd_arm64": [
+ "go1.26.3.netbsd-arm64.tar.gz",
+ "faca070ad7866db5f5a085fe4380408394e2427e093e9770146620c0db508251"
+ ],
+ "openbsd_386": [
+ "go1.26.3.openbsd-386.tar.gz",
+ "a29ad1b1f1a0a3a0f7e70a579f8ab1a26c03778bdcae4f58bd5a29f303104af9"
+ ],
+ "openbsd_amd64": [
+ "go1.26.3.openbsd-amd64.tar.gz",
+ "b2d952b8f0b74a6d2c1a01251aca75ec8eb00a505ebc993f192b792c6762c800"
+ ],
+ "openbsd_arm": [
+ "go1.26.3.openbsd-arm.tar.gz",
+ "1038789f09e31a6b7b5cd7a5e5b3f65cb88ceefb68e34875a7e41b1a28fe2fb7"
+ ],
+ "openbsd_arm64": [
+ "go1.26.3.openbsd-arm64.tar.gz",
+ "1e2df1dc7a4af8bf2a937e7641f300b855bf12bb84a01c44d00a2d68ec18ce26"
+ ],
+ "openbsd_ppc64": [
+ "go1.26.3.openbsd-ppc64.tar.gz",
+ "42ac85fff0f26a1121ba94d7677f6c51cf3d92b53ad2980e54d80f0b196d57a9"
+ ],
+ "openbsd_riscv64": [
+ "go1.26.3.openbsd-riscv64.tar.gz",
+ "c3ada901258530e4ccb58d58537fb9203733ef76155e589125fd2de2e33e857a"
+ ],
+ "plan9_386": [
+ "go1.26.3.plan9-386.tar.gz",
+ "0c5ee46c1345f16edb9ed7317050c20178fdb2b67f0adc2d7f5cf9339147bee5"
+ ],
+ "plan9_amd64": [
+ "go1.26.3.plan9-amd64.tar.gz",
+ "d672908489ef1982b63110597e1804656a5a9519544337af382233a171a1c96e"
+ ],
+ "plan9_arm": [
+ "go1.26.3.plan9-arm.tar.gz",
+ "8ff8f45a52b4900febf8ecf0aa9ac0d49233c76fa4efe405e6ff0d81a6a50749"
+ ],
+ "solaris_amd64": [
+ "go1.26.3.solaris-amd64.tar.gz",
+ "e9c5eab8d081c57fad50895b99e18faf78cccbbe957dea231eba3a32c964d7e7"
+ ],
+ "windows_386": [
+ "go1.26.3.windows-386.zip",
+ "cefec7bd234f57dcc22e2ad2b2e98e45840d998770c5b10b22daddf728dc7cac"
+ ],
+ "windows_amd64": [
+ "go1.26.3.windows-amd64.zip",
+ "20d2ceafb4ed41b96b879010927b28bc92a5be57a7c1801ce365a9ca51d3224a"
+ ],
+ "windows_arm64": [
+ "go1.26.3.windows-arm64.zip",
+ "95cd63bc6b0da77409ba819215afea9ddf5702c55a3b20af3dd90ea95c7b130c"
+ ]
+ }
+ }
+ }
+}
diff --git a/Makefile b/Makefile
index 504c22e47..44805dfbd 100644
--- a/Makefile
+++ b/Makefile
@@ -48,24 +48,18 @@ GOFILES=$(shell find . -name '*.go' -a ! -name '*_test.go')
GOTESTFILES=$(shell find . -name '*_test.go')
-GOGENFILES=internal/runtime/compiler/parser/parser.go\
- internal/mtail/logo.ico.go
+GOGENFILES=internal/runtime/compiler/parser/parser.go
CLEANFILES+=\
internal/runtime/compiler/parser/parser.go\
internal/runtime/compiler/parser/y.output\
- internal/mtail/logo.ico.go\
internal/mtail/logo.ico\
# A place to install tool dependencies.
GOBIN ?= $(firstword $(subst :, ,$(shell go env GOPATH)))/bin
export PATH := $(GOBIN):$(PATH)
-TOGO = $(GOBIN)/togo
-$(TOGO):
- go install github.com/flazz/togo@latest
-
GOYACC = $(GOBIN)/goyacc
$(GOYACC):
go install golang.org/x/tools/cmd/goyacc@latest
@@ -144,10 +138,6 @@ internal/runtime/compiler/parser/parser.go: internal/runtime/compiler/parser/par
internal/mtail/logo.ico: logo.png
/usr/bin/convert $< -define icon:auto-resize=64,48,32,16 $@ || touch $@
-internal/mtail/logo.ico.go: | internal/mtail/logo.ico $(TOGO)
- togo -pkg mtail -name logoFavicon -input internal/mtail/logo.ico
-
-
###
## Emit the current toolchain version at the start of every goal, if that goal depends on this.
#
diff --git a/README.md b/README.md
index 74201ab5c..b8d8cfcc7 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
-
+
# mtail - extract internal monitoring data from application logs for collection into a timeseries database
-[](https://github.com/google/mtail/actions?query=workflow%3ACI+branch%3main)
-[](http://godoc.org/github.com/google/mtail)
-[](https://goreportcard.com/report/github.com/google/mtail)
+[](https://github.com/jaqx0r/mtail/actions?query=workflow%3ACI+branch%3main)
+[](http://godoc.org/github.com/jaqx0r/mtail)
+[](https://goreportcard.com/report/github.com/jaqx0r/mtail)
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mtail)
-[](https://codecov.io/gh/google/mtail)
+[](https://codecov.io/gh/jaqx0r/mtail)
`mtail` is a tool for extracting metrics from application logs to be exported
into a timeseries database or timeseries calculator for alerting and
@@ -17,7 +17,7 @@ export their own internal state (other than via logs) and existing monitoring
systems, such that system operators do not need to patch those applications to
instrument them or writing custom extraction code for every such application.
-The extraction is controlled by [mtail programs](docs/Programming-Guide.md)
+The extraction is controlled by [mtail programs](https://jaqx0r.github.io/mtail/Programming-Guide)
which define patterns and actions:
# simple line counter
@@ -30,7 +30,7 @@ Metrics are exported for scraping by a collector as JSON or Prometheus format
over HTTP, or can be periodically sent to a collectd, StatsD, or Graphite
collector socket.
-Read the [programming guide](docs/Programming-Guide.md) if you want to learn how
+Read the [programming guide](https://jaqx0r.github.io/mtail/Programming-Guide) if you want to learn how
to write mtail programs.
Ask general questions on the users mailing list: https://groups.google.com/g/mtail-users
@@ -42,36 +42,34 @@ There are various ways of installing **mtail**.
### Precompiled binaries
Precompiled binaries for released versions are available in the
-[Releases page](https://github.com/google/mtail/releases) on Github. Using the
+[Releases page](https://github.com/jaqx0r/mtail/releases) on Github. Using the
latest production release binary is the recommended way of installing **mtail**.
Windows, OSX and Linux binaries are available.
### Building from source
-The simplest way to get `mtail` is to `go get` it directly.
+`mtail` uses [`bazel`](https://bazel.build) for its speed, hermeticity, and support for cross-language compilation. Install [`bazelisk`](https://bazel.build/install/bazelisk) to manage Bazel for you.
-`go get github.com/google/mtail/cmd/mtail`
-
-This assumes you have a working Go environment with a recent Go version. Usually mtail is tested to work with the last two minor versions (e.g. Go 1.12 and Go 1.11).
-
-If you want to fetch everything, you need to turn on Go Modules to succeed because of the way Go Modules have changed the way go get treats source trees with no Go code at the top level.
+Then:
```
-GO111MODULE=on go get -u github.com/google/mtail
-cd $GOPATH/src/github.com/google/mtail
-make install
+bazel build //cmd/mtail
```
-If you develop the compiler you will need some additional tools
-like `goyacc` to be able to rebuild the parser.
+See the [Build instructions](https://jaqx0r.github.io/mtail/Building) for more details.
-See the [Build instructions](docs/Building.md) for more details.
+The build system can also emit an OCI container image for you.
+
+```
+bazel build //:oci_image
+```
-A `Dockerfile` is included in this repository for local development as an
-alternative to installing Go in your environment, and takes care of all the
-build dependency installation, if you don't care for that.
+will create it, but to run it the best option is to load it into your local container runtime
+```
+bazel run //:load_image
+```
## Deployment
@@ -85,36 +83,38 @@ alerting tool, like [Prometheus](http://prometheus.io).
to!](http://www.imdb.com/title/tt0151804/quotes/?item=qt0386890) It has the
extraction skills! It is good at dealing with log files!!
+Learn more about [interoperability with other tools](https://jaqx0r.github.io/mtail/Interoperability)
+
## Read More
-Full documentation at http://google.github.io/mtail/
+Full documentation at https://jaqx0r.github.io/mtail/
Read more about writing `mtail` programs:
-* [Programming Guide](docs/Programming-Guide.md)
-* [Language Reference](docs/Language.md)
-* [Metrics](docs/Metrics.md)
-* [Managing internal state](docs/state.md)
-* [Testing your programs](docs/Testing.md)
+* [Programming Guide](https://jaqx0r.github.io/mtail/Programming-Guide)
+* [Language Reference](https://jaqx0r.github.io/mtail/Language)
+* [Metrics](https://jaqx0r.github.io/mtail/Metrics)
+* [Managing internal state](https://jaqx0r.github.io/mtail/state)
+* [Testing your programs](https://jaqx0r.github.io/mtail/Testing)
Read more about hacking on `mtail`
-* [Building from source](docs/Building.md)
+* [Building from source](https://jaqx0r.github.io/mtail/Building)
* [Contributing](CONTRIBUTING.md)
-* [Style](docs/style.md)
+* [Style](https://jaqx0r.github.io/mtail/style)
Read more about deploying `mtail` and your programs in a monitoring environment
-* [Deploying](docs/Deploying.md)
-* [Interoperability](docs/Interoperability.md) with other systems
-* [Troubleshooting](docs/Troubleshooting.md)
-* [FAQ](docs/faq.md)
+* [Deploying](https://jaqx0r.github.io/mtail/Deploying)
+* [Interoperability](https://jaqx0r.github.io/mtail/Interoperability) with other systems
+* [Troubleshooting](https://jaqx0r.github.io/mtail/Troubleshooting)
+* [FAQ](https://jaqx0r.github.io/mtail/faq)
## Getting more help and reporting defects
-If you have any questions, please use the [GitHub Discussions Q&A](https://github.com/google/mtail/discussions/new?category=q-a).
+If you have any questions, please use the [GitHub Discussions Q&A](https://github.com/jaqx0r/mtail/discussions/new?category=q-a).
We also have an email list : https://groups.google.com/forum/#!forum/mtail-users
-For any defects please [file a new issue](https://github.com/google/mtail/issues/new).
+For any defects please [file a new issue](https://github.com/jaqx0r/mtail/issues/new).
diff --git a/TODO b/TODO
index a887b5843..bb018df50 100644
--- a/TODO
+++ b/TODO
@@ -7,10 +7,6 @@ Can't put trailing newlines in cases in parser test, requires changes to expr st
parse tree/ast testing? - expected AST as result from parse/check instead of
merely getting a result. A similar version of this is in codegen_test.go:TestCodeGenFromAST
-A mapping between progs and logs to reduce wasted processing- issue #35
- Means we don't fan out log lines to every VM if reading from multiple sources.
- Requires figuring out how to provide this configuration. Special syntax in a program? Not very flexible. A real config file? Been trying to avoid that. Commandline flag? Seems difficult to maintain.
-
bytecode like
[{push 1} {push 0} {cmp 1}
{jm 6} {push 0} {jmp 7} {push 1} {jnm 13}
diff --git a/build/BUILD.bazel b/build/BUILD.bazel
new file mode 100644
index 000000000..e69de29bb
diff --git a/build/goyacc.bzl b/build/goyacc.bzl
new file mode 100644
index 000000000..a8ff374e8
--- /dev/null
+++ b/build/goyacc.bzl
@@ -0,0 +1,40 @@
+"""Provides go_yacc rule."""
+
+_GO_YACC_TOOL = "@org_golang_x_tools//cmd/goyacc"
+
+def _go_yacc_impl(ctx):
+ args = ctx.actions.args()
+ args.add("-o", ctx.outputs.out)
+ args.add("-p", ctx.attr.prefix)
+ args.add(ctx.file.src)
+ goroot = "%s/.." % ctx.executable._go_yacc_tool.dirname
+ ctx.actions.run(
+ mnemonic = "GoYacc",
+ executable = ctx.executable._go_yacc_tool,
+ arguments = [args],
+ inputs = [ctx.file.src],
+ outputs = [ctx.outputs.out],
+ env = {
+ "GOROOT": goroot,
+ },
+ )
+ return DefaultInfo(
+ files = depset([ctx.outputs.out]),
+ )
+
+go_yacc = rule(
+ implementation = _go_yacc_impl,
+ attrs = {
+ "src": attr.label(
+ allow_single_file = True,
+ ),
+ "out": attr.output(),
+ "prefix": attr.string(),
+ "_go_yacc_tool": attr.label(
+ default = _GO_YACC_TOOL,
+ allow_single_file = True,
+ executable = True,
+ cfg = "exec",
+ ),
+ },
+)
diff --git a/build/tools.go b/build/tools.go
new file mode 100644
index 000000000..49889c499
--- /dev/null
+++ b/build/tools.go
@@ -0,0 +1,7 @@
+//go:build tools
+
+package tools
+
+import (
+ _ "golang.org/x/tools/cmd/goyacc"
+)
diff --git a/build/workspace_status.sh b/build/workspace_status.sh
new file mode 100755
index 000000000..e18352e4c
--- /dev/null
+++ b/build/workspace_status.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+echo STABLE_GIT_BRANCH $(git --no-pager rev-parse --abbrev-ref HEAD)
+echo STABLE_GIT_VERSION $(git --no-pager describe --tags --always --dirty)
+echo STABLE_GIT_REVISION $(git --no-pager rev-parse HEAD)
+
+# Convert a version + commit count into a SemVer.
+echo STABLE_GIT_SEMVER $(git --no-pager describe --tags | sed -e 's/^v//' -e 's/-/./' -e 's/-.*$//')
+
+# volatiles
+# RFC 3339 ISO 8601 format for the OCI image.
+echo BUILD_TIMESTAMP_ISO8601 $(date --iso-8601=seconds --utc | sed -e 's/+00:00/Z/')
diff --git a/cmd/mdot/BUILD.bazel b/cmd/mdot/BUILD.bazel
new file mode 100644
index 000000000..43a137453
--- /dev/null
+++ b/cmd/mdot/BUILD.bazel
@@ -0,0 +1,21 @@
+load("@rules_go//go:def.bzl", "go_binary", "go_library")
+
+go_library(
+ name = "mdot_lib",
+ srcs = ["main.go"],
+ importpath = "github.com/jaqx0r/mtail/cmd/mdot",
+ visibility = ["//visibility:private"],
+ deps = [
+ "//internal/mtail",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/checker",
+ "//internal/runtime/compiler/parser",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_binary(
+ name = "mdot",
+ embed = [":mdot_lib"],
+ visibility = ["//visibility:public"],
+)
diff --git a/cmd/mdot/main.go b/cmd/mdot/main.go
index 9d3cc1020..42a07f4c4 100644
--- a/cmd/mdot/main.go
+++ b/cmd/mdot/main.go
@@ -6,11 +6,11 @@ Command mdot turns an mtail program AST into a graphviz graph on standard output
To use, run it like (assuming your shell is in the same directory as this file)
- go run github.com/google/mtail/cmd/mdot --prog ../../examples/dhcpd.mtail | xdot -
+ go run github.com/jaqx0r/mtail/cmd/mdot --prog ../../examples/dhcpd.mtail | xdot -
or
- go run github.com/google/mtail/cmd/mdot --prog ../../examples/dhcpd.mtail --http_port 8080
+ go run github.com/jaqx0r/mtail/cmd/mdot --prog ../../examples/dhcpd.mtail --http_port 8080
to view the dot output visit http://localhost:8080
@@ -29,10 +29,10 @@ import (
"strings"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/checker"
- "github.com/google/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/checker"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
)
var (
diff --git a/cmd/mfmt/BUILD.bazel b/cmd/mfmt/BUILD.bazel
new file mode 100644
index 000000000..3c8db4ba5
--- /dev/null
+++ b/cmd/mfmt/BUILD.bazel
@@ -0,0 +1,19 @@
+load("@rules_go//go:def.bzl", "go_binary", "go_library")
+
+go_library(
+ name = "mfmt_lib",
+ srcs = ["main.go"],
+ importpath = "github.com/jaqx0r/mtail/cmd/mfmt",
+ visibility = ["//visibility:private"],
+ deps = [
+ "//internal/runtime/compiler/checker",
+ "//internal/runtime/compiler/parser",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_binary(
+ name = "mfmt",
+ embed = [":mfmt_lib"],
+ visibility = ["//visibility:public"],
+)
diff --git a/cmd/mfmt/main.go b/cmd/mfmt/main.go
index 0afcecfd5..d9fb14790 100644
--- a/cmd/mfmt/main.go
+++ b/cmd/mfmt/main.go
@@ -13,8 +13,8 @@ import (
"os"
"github.com/golang/glog"
- "github.com/google/mtail/internal/runtime/compiler/checker"
- "github.com/google/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/checker"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
)
var (
diff --git a/cmd/mgen/BUILD.bazel b/cmd/mgen/BUILD.bazel
new file mode 100644
index 000000000..c848ea7c9
--- /dev/null
+++ b/cmd/mgen/BUILD.bazel
@@ -0,0 +1,15 @@
+load("@rules_go//go:def.bzl", "go_binary", "go_library")
+
+go_library(
+ name = "mgen_lib",
+ srcs = ["main.go"],
+ importpath = "github.com/jaqx0r/mtail/cmd/mgen",
+ visibility = ["//visibility:private"],
+ deps = ["//internal/runtime/compiler/parser"],
+)
+
+go_binary(
+ name = "mgen",
+ embed = [":mgen_lib"],
+ visibility = ["//visibility:public"],
+)
diff --git a/cmd/mgen/main.go b/cmd/mgen/main.go
index 0f18245aa..2c9465e9c 100644
--- a/cmd/mgen/main.go
+++ b/cmd/mgen/main.go
@@ -9,7 +9,7 @@ import (
"fmt"
"math/rand"
- "github.com/google/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
)
var (
diff --git a/cmd/mtail/BUILD.bazel b/cmd/mtail/BUILD.bazel
new file mode 100644
index 000000000..e69c5dfec
--- /dev/null
+++ b/cmd/mtail/BUILD.bazel
@@ -0,0 +1,28 @@
+load("@rules_go//go:def.bzl", "go_binary", "go_cross_binary", "go_library")
+
+go_library(
+ name = "mtail_lib",
+ srcs = ["main.go"],
+ importpath = "github.com/jaqx0r/mtail/cmd/mtail",
+ visibility = ["//visibility:private"],
+ deps = [
+ "//internal/exporter",
+ "//internal/metrics",
+ "//internal/mtail",
+ "//internal/waker",
+ "@com_github_golang_glog//:glog",
+ "@io_opencensus_go//trace",
+ ],
+)
+
+go_binary(
+ name = "mtail",
+ embed = [":mtail_lib"],
+ visibility = ["//visibility:public"],
+ x_defs = {
+ "main.Branch": "{STABLE_GIT_BRANCH}",
+ "main.Version": "{STABLE_GIT_VERSION}",
+ "main.Revision": "{STABLE_GIT_REVISION}",
+ "main.EmbedLabel": "{BUILD_EMBED_LABEL}",
+ },
+)
diff --git a/cmd/mtail/main.go b/cmd/mtail/main.go
index e1685db24..ccf98a467 100644
--- a/cmd/mtail/main.go
+++ b/cmd/mtail/main.go
@@ -15,10 +15,10 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/exporter"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/exporter"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/waker"
"go.opencensus.io/trace"
)
@@ -90,13 +90,17 @@ func init() {
}
var (
- // Branch as well as Version and Revision identifies where in the git
- // history the build came from, as supplied by the linker when copmiled
- // with `make'. The defaults here indicate that the user did not use
- // `make' as instructed.
- Branch = "invalid:-use-make-to-build"
- Version = "invalid:-use-make-to-build"
- Revision = "invalid:-use-make-to-build"
+ // Branch, Version and Revision identifies where in the git history the
+ // build came from, as supplied by the linker when compiled with `bazel`.
+ // The defaults here indicate that the user did not use `bazel` as
+ // instructed.
+ Branch = "invalid:-use-bazel-to-build"
+ Version = "invalid:-use-bazel-to-build"
+ Revision = "invalid:-use-bazel-to-build"
+ // EmbedLabel can be set on the bazel command line with `--embed_label` and
+ // is used during releases to inject the release version name into the
+ // build.
+ EmbedLabel = ""
)
func main() {
@@ -104,6 +108,7 @@ func main() {
Branch: Branch,
Version: Version,
Revision: Revision,
+ EmbedLabel: EmbedLabel,
}
flag.Usage = func() {
diff --git a/deps.bzl b/deps.bzl
new file mode 100644
index 000000000..27e0cadda
--- /dev/null
+++ b/deps.bzl
@@ -0,0 +1,1494 @@
+load("@bazel_gazelle//:deps.bzl", "go_repository")
+
+def go_dependencies():
+ go_repository(
+ name = "co_honnef_go_tools",
+ build_file_proto_mode = "disable_global",
+ importpath = "honnef.co/go/tools",
+ sum = "h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=",
+ version = "v0.0.1-2020.1.3",
+ )
+ go_repository(
+ name = "com_github_alecthomas_kingpin_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/alecthomas/kingpin/v2",
+ sum = "h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=",
+ version = "v2.4.0",
+ )
+ go_repository(
+ name = "com_github_alecthomas_units",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/alecthomas/units",
+ sum = "h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=",
+ version = "v0.0.0-20211218093645-b94a6e3cc137",
+ )
+ go_repository(
+ name = "com_github_bazelbuild_rules_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/bazelbuild/rules_go",
+ sum = "h1:ZPsHcsau3SXFQJOpqD+Ey9/RU6qjiUhdTAZI+Q8e2gY=",
+ version = "v0.45.0",
+ )
+ go_repository(
+ name = "com_github_beorn7_perks",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/beorn7/perks",
+ sum = "h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=",
+ version = "v1.0.1",
+ )
+ go_repository(
+ name = "com_github_burntsushi_toml",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/BurntSushi/toml",
+ sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=",
+ version = "v0.3.1",
+ )
+ go_repository(
+ name = "com_github_burntsushi_xgb",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/BurntSushi/xgb",
+ sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=",
+ version = "v0.0.0-20160522181843-27f122750802",
+ )
+ go_repository(
+ name = "com_github_census_instrumentation_opencensus_proto",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/census-instrumentation/opencensus-proto",
+ sum = "h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=",
+ version = "v0.4.1",
+ )
+ go_repository(
+ name = "com_github_cespare_xxhash_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/cespare/xxhash/v2",
+ sum = "h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=",
+ version = "v2.2.0",
+ )
+ go_repository(
+ name = "com_github_chzyer_logex",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/chzyer/logex",
+ sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=",
+ version = "v1.1.10",
+ )
+ go_repository(
+ name = "com_github_chzyer_readline",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/chzyer/readline",
+ sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=",
+ version = "v0.0.0-20180603132655-2972be24d48e",
+ )
+ go_repository(
+ name = "com_github_chzyer_test",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/chzyer/test",
+ sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=",
+ version = "v0.0.0-20180213035817-a1ea475d72b1",
+ )
+ go_repository(
+ name = "com_github_client9_misspell",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/client9/misspell",
+ sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=",
+ version = "v0.3.4",
+ )
+ go_repository(
+ name = "com_github_cncf_udpa_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/cncf/udpa/go",
+ sum = "h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=",
+ version = "v0.0.0-20220112060539-c52dc94e7fbe",
+ )
+ go_repository(
+ name = "com_github_cncf_xds_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/cncf/xds/go",
+ sum = "h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=",
+ version = "v0.0.0-20230607035331-e9ce68804cb4",
+ )
+ go_repository(
+ name = "com_github_davecgh_go_spew",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/davecgh/go-spew",
+ sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
+ version = "v1.1.1",
+ )
+ go_repository(
+ name = "com_github_envoyproxy_go_control_plane",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/envoyproxy/go-control-plane",
+ sum = "h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=",
+ version = "v0.11.1-0.20230524094728-9239064ad72f",
+ )
+ go_repository(
+ name = "com_github_envoyproxy_protoc_gen_validate",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/envoyproxy/protoc-gen-validate",
+ sum = "h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=",
+ version = "v0.10.1",
+ )
+ go_repository(
+ name = "com_github_go_gl_glfw",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/go-gl/glfw",
+ sum = "h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=",
+ version = "v0.0.0-20190409004039-e6da0acd62b1",
+ )
+ go_repository(
+ name = "com_github_go_gl_glfw_v3_3_glfw",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/go-gl/glfw/v3.3/glfw",
+ sum = "h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=",
+ version = "v0.0.0-20200222043503-6f7a984d4dc4",
+ )
+ go_repository(
+ name = "com_github_go_kit_log",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/go-kit/log",
+ sum = "h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=",
+ version = "v0.2.1",
+ )
+ go_repository(
+ name = "com_github_go_logfmt_logfmt",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/go-logfmt/logfmt",
+ sum = "h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=",
+ version = "v0.5.1",
+ )
+ go_repository(
+ name = "com_github_gogo_protobuf",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/gogo/protobuf",
+ sum = "h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=",
+ version = "v1.3.2",
+ )
+ go_repository(
+ name = "com_github_golang_glog",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/golang/glog",
+ sum = "h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=",
+ version = "v1.2.0",
+ )
+ go_repository(
+ name = "com_github_golang_groupcache",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/golang/groupcache",
+ sum = "h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=",
+ version = "v0.0.0-20210331224755-41bb18bfe9da",
+ )
+ go_repository(
+ name = "com_github_golang_mock",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/golang/mock",
+ sum = "h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=",
+ version = "v1.7.0-rc.1",
+ )
+ go_repository(
+ name = "com_github_golang_protobuf",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/golang/protobuf",
+ sum = "h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=",
+ version = "v1.5.3",
+ )
+ go_repository(
+ name = "com_github_google_btree",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/google/btree",
+ sum = "h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=",
+ version = "v1.0.0",
+ )
+ go_repository(
+ name = "com_github_google_go_cmp",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/google/go-cmp",
+ sum = "h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=",
+ version = "v0.6.0",
+ )
+ go_repository(
+ name = "com_github_google_martian",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/google/martian",
+ sum = "h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=",
+ version = "v2.1.0+incompatible",
+ )
+ go_repository(
+ name = "com_github_google_pprof",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/google/pprof",
+ sum = "h1:SRgJV+IoxM5MKyFdlSUeNy6/ycRUF2yBAKdAQswoHUk=",
+ version = "v0.0.0-20200229191704-1ebb73c60ed3",
+ )
+ go_repository(
+ name = "com_github_google_renameio",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/google/renameio",
+ sum = "h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=",
+ version = "v0.1.0",
+ )
+ go_repository(
+ name = "com_github_google_uuid",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/google/uuid",
+ sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=",
+ version = "v1.3.0",
+ )
+ go_repository(
+ name = "com_github_googleapis_enterprise_certificate_proxy",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/googleapis/enterprise-certificate-proxy",
+ sum = "h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=",
+ version = "v0.2.0",
+ )
+ go_repository(
+ name = "com_github_googleapis_gax_go_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/googleapis/gax-go/v2",
+ sum = "h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=",
+ version = "v2.7.0",
+ )
+ go_repository(
+ name = "com_github_hashicorp_golang_lru",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/hashicorp/golang-lru",
+ sum = "h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=",
+ version = "v0.5.1",
+ )
+ go_repository(
+ name = "com_github_ianlancetaylor_demangle",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/ianlancetaylor/demangle",
+ sum = "h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=",
+ version = "v0.0.0-20181102032728-5e5cf60278f6",
+ )
+ go_repository(
+ name = "com_github_jpillora_backoff",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/jpillora/backoff",
+ sum = "h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=",
+ version = "v1.0.0",
+ )
+ go_repository(
+ name = "com_github_json_iterator_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/json-iterator/go",
+ sum = "h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=",
+ version = "v1.1.12",
+ )
+ go_repository(
+ name = "com_github_jstemmer_go_junit_report",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/jstemmer/go-junit-report",
+ sum = "h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=",
+ version = "v0.9.1",
+ )
+ go_repository(
+ name = "com_github_julienschmidt_httprouter",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/julienschmidt/httprouter",
+ sum = "h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=",
+ version = "v1.3.0",
+ )
+ go_repository(
+ name = "com_github_kisielk_gotool",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/kisielk/gotool",
+ sum = "h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=",
+ version = "v1.0.0",
+ )
+ go_repository(
+ name = "com_github_kr_pretty",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/kr/pretty",
+ sum = "h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=",
+ version = "v0.3.1",
+ )
+ go_repository(
+ name = "com_github_kr_pty",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/kr/pty",
+ sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=",
+ version = "v1.1.1",
+ )
+ go_repository(
+ name = "com_github_kr_text",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/kr/text",
+ sum = "h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=",
+ version = "v0.1.0",
+ )
+ go_repository(
+ name = "com_github_modern_go_concurrent",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/modern-go/concurrent",
+ sum = "h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=",
+ version = "v0.0.0-20180306012644-bacd9c7ef1dd",
+ )
+ go_repository(
+ name = "com_github_modern_go_reflect2",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/modern-go/reflect2",
+ sum = "h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=",
+ version = "v1.0.2",
+ )
+ go_repository(
+ name = "com_github_mwitkow_go_conntrack",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/mwitkow/go-conntrack",
+ sum = "h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=",
+ version = "v0.0.0-20190716064945-2f068394615f",
+ )
+ go_repository(
+ name = "com_github_pkg_errors",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/pkg/errors",
+ sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=",
+ version = "v0.9.1",
+ )
+ go_repository(
+ name = "com_github_pmezard_go_difflib",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/pmezard/go-difflib",
+ sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=",
+ version = "v1.0.0",
+ )
+ go_repository(
+ name = "com_github_prometheus_client_golang",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/prometheus/client_golang",
+ sum = "h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=",
+ version = "v1.19.0",
+ )
+ go_repository(
+ name = "com_github_prometheus_client_model",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/prometheus/client_model",
+ sum = "h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=",
+ version = "v0.5.0",
+ )
+ go_repository(
+ name = "com_github_prometheus_common",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/prometheus/common",
+ sum = "h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=",
+ version = "v0.48.0",
+ )
+ go_repository(
+ name = "com_github_prometheus_procfs",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/prometheus/procfs",
+ sum = "h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=",
+ version = "v0.12.0",
+ )
+ go_repository(
+ name = "com_github_rogpeppe_go_internal",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/rogpeppe/go-internal",
+ sum = "h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_github_stretchr_objx",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/stretchr/objx",
+ sum = "h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=",
+ version = "v0.5.0",
+ )
+ go_repository(
+ name = "com_github_stretchr_testify",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/stretchr/testify",
+ sum = "h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=",
+ version = "v1.8.1",
+ )
+ go_repository(
+ name = "com_github_uber_jaeger_client_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/uber/jaeger-client-go",
+ sum = "h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=",
+ version = "v2.25.0+incompatible",
+ )
+ go_repository(
+ name = "com_github_xhit_go_str2duration_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/xhit/go-str2duration/v2",
+ sum = "h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=",
+ version = "v2.1.0",
+ )
+ go_repository(
+ name = "com_github_yuin_goldmark",
+ build_file_proto_mode = "disable_global",
+ importpath = "github.com/yuin/goldmark",
+ sum = "h1:isv+Q6HQAmmL2Ofcmg8QauBmDPlUUnSoNhEcC940Rds=",
+ version = "v1.1.25",
+ )
+ go_repository(
+ name = "com_google_cloud_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go",
+ sum = "h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=",
+ version = "v0.110.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_accessapproval",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/accessapproval",
+ sum = "h1:x0cEHro/JFPd7eS4BlEWNTMecIj2HdXjOVB5BtvwER0=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_accesscontextmanager",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/accesscontextmanager",
+ sum = "h1:MG60JgnEoawHJrbWw0jGdv6HLNSf6gQvYRiXpuzqgEA=",
+ version = "v1.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_aiplatform",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/aiplatform",
+ sum = "h1:zTw+suCVchgZyO+k847wjzdVjWmrAuehxdvcZvJwfGg=",
+ version = "v1.37.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_analytics",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/analytics",
+ sum = "h1:LqAo3tAh2FU9+w/r7vc3hBjU23Kv7GhO/PDIW7kIYgM=",
+ version = "v0.19.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_apigateway",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/apigateway",
+ sum = "h1:ZI9mVO7x3E9RK/BURm2p1aw9YTBSCQe3klmyP1WxWEg=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_apigeeconnect",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/apigeeconnect",
+ sum = "h1:sWOmgDyAsi1AZ48XRHcATC0tsi9SkPT7DA/+VCfkaeA=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_apigeeregistry",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/apigeeregistry",
+ sum = "h1:E43RdhhCxdlV+I161gUY2rI4eOaMzHTA5kNkvRsFXvc=",
+ version = "v0.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_apikeys",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/apikeys",
+ sum = "h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ=",
+ version = "v0.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_appengine",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/appengine",
+ sum = "h1:aBGDKmRIaRRoWJ2tAoN0oVSHoWLhtO9aj/NvUyP4aYs=",
+ version = "v1.7.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_area120",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/area120",
+ sum = "h1:ugckkFh4XkHJMPhTIx0CyvdoBxmOpMe8rNs4Ok8GAag=",
+ version = "v0.7.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_artifactregistry",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/artifactregistry",
+ sum = "h1:o1Q80vqEB6Qp8WLEH3b8FBLNUCrGQ4k5RFj0sn/sgO8=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_asset",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/asset",
+ sum = "h1:YAsssO08BqZ6mncbb6FPlj9h6ACS7bJQUOlzciSfbNk=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_assuredworkloads",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/assuredworkloads",
+ sum = "h1:VLGnVFta+N4WM+ASHbhc14ZOItOabDLH1MSoDv+Xuag=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_automl",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/automl",
+ sum = "h1:50VugllC+U4IGl3tDNcZaWvApHBTrn/TvyHDJ0wM+Uw=",
+ version = "v1.12.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_baremetalsolution",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/baremetalsolution",
+ sum = "h1:2AipdYXL0VxMboelTTw8c1UJ7gYu35LZYUbuRv9Q28s=",
+ version = "v0.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_batch",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/batch",
+ sum = "h1:YbMt0E6BtqeD5FvSv1d56jbVsWEzlGm55lYte+M6Mzs=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_beyondcorp",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/beyondcorp",
+ sum = "h1:UkY2BTZkEUAVrgqnSdOJ4p3y9ZRBPEe1LkjgC8Bj/Pc=",
+ version = "v0.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_bigquery",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/bigquery",
+ sum = "h1:RscMV6LbnAmhAzD893Lv9nXXy2WCaJmbxYPWDLbGqNQ=",
+ version = "v1.50.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_billing",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/billing",
+ sum = "h1:JYj28UYF5w6VBAh0gQYlgHJ/OD1oA+JgW29YZQU+UHM=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_binaryauthorization",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/binaryauthorization",
+ sum = "h1:d3pMDBCCNivxt5a4eaV7FwL7cSH0H7RrEnFrTb1QKWs=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_certificatemanager",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/certificatemanager",
+ sum = "h1:5C5UWeSt8Jkgp7OWn2rCkLmYurar/vIWIoSQ2+LaTOc=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_channel",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/channel",
+ sum = "h1:GpcQY5UJKeOekYgsX3QXbzzAc/kRGtBq43fTmyKe6Uw=",
+ version = "v1.12.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_cloudbuild",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/cloudbuild",
+ sum = "h1:GHQCjV4WlPPVU/j3Rlpc8vNIDwThhd1U9qSY/NPZdko=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_clouddms",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/clouddms",
+ sum = "h1:E7v4TpDGUyEm1C/4KIrpVSOCTm0P6vWdHT0I4mostRA=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_cloudtasks",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/cloudtasks",
+ sum = "h1:uK5k6abf4yligFgYFnG0ni8msai/dSv6mDmiBulU0hU=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_compute",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/compute",
+ sum = "h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=",
+ version = "v1.19.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_compute_metadata",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/compute/metadata",
+ sum = "h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=",
+ version = "v0.2.3",
+ )
+ go_repository(
+ name = "com_google_cloud_go_contactcenterinsights",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/contactcenterinsights",
+ sum = "h1:jXIpfcH/VYSE1SYcPzO0n1VVb+sAamiLOgCw45JbOQk=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_container",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/container",
+ sum = "h1:NKlY/wCDapfVZlbVVaeuu2UZZED5Dy1z4Zx1KhEzm8c=",
+ version = "v1.15.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_containeranalysis",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/containeranalysis",
+ sum = "h1:EQ4FFxNaEAg8PqQCO7bVQfWz9NVwZCUKaM1b3ycfx3U=",
+ version = "v0.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_datacatalog",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/datacatalog",
+ sum = "h1:4H5IJiyUE0X6ShQBqgFFZvGGcrwGVndTwUSLP4c52gw=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dataflow",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dataflow",
+ sum = "h1:eYyD9o/8Nm6EttsKZaEGD84xC17bNgSKCu0ZxwqUbpg=",
+ version = "v0.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dataform",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dataform",
+ sum = "h1:Dyk+fufup1FR6cbHjFpMuP4SfPiF3LI3JtoIIALoq48=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_datafusion",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/datafusion",
+ sum = "h1:sZjRnS3TWkGsu1LjYPFD/fHeMLZNXDK6PDHi2s2s/bk=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_datalabeling",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/datalabeling",
+ sum = "h1:ch4qA2yvddGRUrlfwrNJCr79qLqhS9QBwofPHfFlDIk=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dataplex",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dataplex",
+ sum = "h1:RvoZ5T7gySwm1CHzAw7yY1QwwqaGswunmqEssPxU/AM=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dataproc",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dataproc",
+ sum = "h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU=",
+ version = "v1.12.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dataqna",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dataqna",
+ sum = "h1:yFzi/YU4YAdjyo7pXkBE2FeHbgz5OQQBVDdbErEHmVQ=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_datastore",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/datastore",
+ sum = "h1:iF6I/HaLs3Ado8uRKMvZRvF/ZLkWaWE9i8AiHzbC774=",
+ version = "v1.11.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_datastream",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/datastream",
+ sum = "h1:BBCBTnWMDwwEzQQmipUXxATa7Cm7CA/gKjKcR2w35T0=",
+ version = "v1.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_deploy",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/deploy",
+ sum = "h1:otshdKEbmsi1ELYeCKNYppwV0UH5xD05drSdBm7ouTk=",
+ version = "v1.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dialogflow",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dialogflow",
+ sum = "h1:uVlKKzp6G/VtSW0E7IH1Y5o0H48/UOCmqksG2riYCwQ=",
+ version = "v1.32.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_dlp",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/dlp",
+ sum = "h1:1JoJqezlgu6NWCroBxr4rOZnwNFILXr4cB9dMaSKO4A=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_documentai",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/documentai",
+ sum = "h1:KM3Xh0QQyyEdC8Gs2vhZfU+rt6OCPF0dwVwxKgLmWfI=",
+ version = "v1.18.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_domains",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/domains",
+ sum = "h1:2ti/o9tlWL4N+wIuWUNH+LbfgpwxPr8J1sv9RHA4bYQ=",
+ version = "v0.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_edgecontainer",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/edgecontainer",
+ sum = "h1:O0YVE5v+O0Q/ODXYsQHmHb+sYM8KNjGZw2pjX2Ws41c=",
+ version = "v1.0.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_errorreporting",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/errorreporting",
+ sum = "h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0=",
+ version = "v0.3.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_essentialcontacts",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/essentialcontacts",
+ sum = "h1:gIzEhCoOT7bi+6QZqZIzX1Erj4SswMPIteNvYVlu+pM=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_eventarc",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/eventarc",
+ sum = "h1:fsJmNeqvqtk74FsaVDU6cH79lyZNCYP8Rrv7EhaB/PU=",
+ version = "v1.11.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_filestore",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/filestore",
+ sum = "h1:ckTEXN5towyTMu4q0uQ1Mde/JwTHur0gXs8oaIZnKfw=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_firestore",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/firestore",
+ sum = "h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_functions",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/functions",
+ sum = "h1:pPDqtsXG2g9HeOQLoquLbmvmb82Y4Ezdo1GXuotFoWg=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_gaming",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/gaming",
+ sum = "h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_gkebackup",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/gkebackup",
+ sum = "h1:za3QZvw6ujR0uyqkhomKKKNoXDyqYGPJies3voUK8DA=",
+ version = "v0.4.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_gkeconnect",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/gkeconnect",
+ sum = "h1:gXYKciHS/Lgq0GJ5Kc9SzPA35NGc3yqu6SkjonpEr2Q=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_gkehub",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/gkehub",
+ sum = "h1:TqCSPsEBQ6oZSJgEYZ3XT8x2gUadbvfwI32YB0kuHCs=",
+ version = "v0.12.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_gkemulticloud",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/gkemulticloud",
+ sum = "h1:8I84Q4vl02rJRsFiinBxl7WCozfdLlUVBQuSrqr9Wtk=",
+ version = "v0.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_gsuiteaddons",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/gsuiteaddons",
+ sum = "h1:1mvhXqJzV0Vg5Fa95QwckljODJJfDFXV4pn+iL50zzA=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_iam",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/iam",
+ sum = "h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=",
+ version = "v0.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_iap",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/iap",
+ sum = "h1:PxVHFuMxmSZyfntKXHXhd8bo82WJ+LcATenq7HLdVnU=",
+ version = "v1.7.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_ids",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/ids",
+ sum = "h1:fodnCDtOXuMmS8LTC2y3h8t24U8F3eKWfhi+3LY6Qf0=",
+ version = "v1.3.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_iot",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/iot",
+ sum = "h1:39W5BFSarRNZfVG0eXI5LYux+OVQT8GkgpHCnrZL2vM=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_kms",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/kms",
+ sum = "h1:7hm1bRqGCA1GBRQUrp831TwJ9TWhP+tvLuP497CQS2g=",
+ version = "v1.10.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_language",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/language",
+ sum = "h1:7Ulo2mDk9huBoBi8zCE3ONOoBrL6UXfAI71CLQ9GEIM=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_lifesciences",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/lifesciences",
+ sum = "h1:uWrMjWTsGjLZpCTWEAzYvyXj+7fhiZST45u9AgasasI=",
+ version = "v0.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_logging",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/logging",
+ sum = "h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I=",
+ version = "v1.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_longrunning",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/longrunning",
+ sum = "h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=",
+ version = "v0.4.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_managedidentities",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/managedidentities",
+ sum = "h1:ZRQ4k21/jAhrHBVKl/AY7SjgzeJwG1iZa+mJ82P+VNg=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_maps",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/maps",
+ sum = "h1:mv9YaczD4oZBZkM5XJl6fXQ984IkJNHPwkc8MUsdkBo=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_mediatranslation",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/mediatranslation",
+ sum = "h1:anPxH+/WWt8Yc3EdoEJhPMBRF7EhIdz426A+tuoA0OU=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_memcache",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/memcache",
+ sum = "h1:8/VEmWCpnETCrBwS3z4MhT+tIdKgR1Z4Tr2tvYH32rg=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_metastore",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/metastore",
+ sum = "h1:QCFhZVe2289KDBQ7WxaHV2rAmPrmRAdLC6gbjUd3HPo=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_monitoring",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/monitoring",
+ sum = "h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_networkconnectivity",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/networkconnectivity",
+ sum = "h1:ZD6b4Pk1jEtp/cx9nx0ZYcL3BKqDa+KixNDZ6Bjs1B8=",
+ version = "v1.11.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_networkmanagement",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/networkmanagement",
+ sum = "h1:8KWEUNGcpSX9WwZXq7FtciuNGPdPdPN/ruDm769yAEM=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_networksecurity",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/networksecurity",
+ sum = "h1:sOc42Ig1K2LiKlzG71GUVloeSJ0J3mffEBYmvu+P0eo=",
+ version = "v0.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_notebooks",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/notebooks",
+ sum = "h1:Kg2K3K7CbSXYJHZ1aGQpf1xi5x2GUvQWf2sFVuiZh8M=",
+ version = "v1.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_optimization",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/optimization",
+ sum = "h1:dj8O4VOJRB4CUwZXdmwNViH1OtI0WtWL867/lnYH248=",
+ version = "v1.3.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_orchestration",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/orchestration",
+ sum = "h1:Vw+CEXo8M/FZ1rb4EjcLv0gJqqw89b7+g+C/EmniTb8=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_orgpolicy",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/orgpolicy",
+ sum = "h1:XDriMWug7sd0kYT1QKofRpRHzjad0bK8Q8uA9q+XrU4=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_osconfig",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/osconfig",
+ sum = "h1:PkSQx4OHit5xz2bNyr11KGcaFccL5oqglFPdTboyqwQ=",
+ version = "v1.11.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_oslogin",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/oslogin",
+ sum = "h1:whP7vhpmc+ufZa90eVpkfbgzJRK/Xomjz+XCD4aGwWw=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_phishingprotection",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/phishingprotection",
+ sum = "h1:l6tDkT7qAEV49MNEJkEJTB6vOO/onbSOcNtAT09HPuA=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_policytroubleshooter",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/policytroubleshooter",
+ sum = "h1:yKAGC4p9O61ttZUswaq9GAn1SZnEzTd0vUYXD7ZBT7Y=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_privatecatalog",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/privatecatalog",
+ sum = "h1:EPEJ1DpEGXLDnmc7mnCAqFmkwUJbIsaLAiLHVOkkwtc=",
+ version = "v0.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_pubsub",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/pubsub",
+ sum = "h1:vCge8m7aUKBJYOgrZp7EsNDf6QMd2CAlXZqWTn3yq6s=",
+ version = "v1.30.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_pubsublite",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/pubsublite",
+ sum = "h1:cb9fsrtpINtETHiJ3ECeaVzrfIVhcGjhhJEjybHXHao=",
+ version = "v1.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_recaptchaenterprise_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/recaptchaenterprise/v2",
+ sum = "h1:6iOCujSNJ0YS7oNymI64hXsjGq60T4FK1zdLugxbzvU=",
+ version = "v2.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_recommendationengine",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/recommendationengine",
+ sum = "h1:VibRFCwWXrFebEWKHfZAt2kta6pS7Tlimsnms0fjv7k=",
+ version = "v0.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_recommender",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/recommender",
+ sum = "h1:ZnFRY5R6zOVk2IDS1Jbv5Bw+DExCI5rFumsTnMXiu/A=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_redis",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/redis",
+ sum = "h1:JoAd3SkeDt3rLFAAxEvw6wV4t+8y4ZzfZcZmddqphQ8=",
+ version = "v1.11.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_resourcemanager",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/resourcemanager",
+ sum = "h1:NRM0p+RJkaQF9Ee9JMnUV9BQ2QBIOq/v8M+Pbv/wmCs=",
+ version = "v1.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_resourcesettings",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/resourcesettings",
+ sum = "h1:8Dua37kQt27CCWHm4h/Q1XqCF6ByD7Ouu49xg95qJzI=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_retail",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/retail",
+ sum = "h1:1Dda2OpFNzIb4qWgFZjYlpP7sxX3aLeypKG6A3H4Yys=",
+ version = "v1.12.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_run",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/run",
+ sum = "h1:ydJQo+k+MShYnBfhaRHSZYeD/SQKZzZLAROyfpeD9zw=",
+ version = "v0.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_scheduler",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/scheduler",
+ sum = "h1:NpQAHtx3sulByTLe2dMwWmah8PWgeoieFPpJpArwFV0=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_secretmanager",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/secretmanager",
+ sum = "h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_security",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/security",
+ sum = "h1:PYvDxopRQBfYAXKAuDpFCKBvDOWPWzp9k/H5nB3ud3o=",
+ version = "v1.13.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_securitycenter",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/securitycenter",
+ sum = "h1:AF3c2s3awNTMoBtMX3oCUoOMmGlYxGOeuXSYHNBkf14=",
+ version = "v1.19.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_servicecontrol",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/servicecontrol",
+ sum = "h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE=",
+ version = "v1.11.1",
+ )
+ go_repository(
+ name = "com_google_cloud_go_servicedirectory",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/servicedirectory",
+ sum = "h1:SJwk0XX2e26o25ObYUORXx6torSFiYgsGkWSkZgkoSU=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_servicemanagement",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/servicemanagement",
+ sum = "h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY=",
+ version = "v1.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_serviceusage",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/serviceusage",
+ sum = "h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_shell",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/shell",
+ sum = "h1:wT0Uw7ib7+AgZST9eCDygwTJn4+bHMDtZo5fh7kGWDU=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_spanner",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/spanner",
+ sum = "h1:7VdjZ8zj4sHbDw55atp5dfY6kn1j9sam9DRNpPQhqR4=",
+ version = "v1.45.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_speech",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/speech",
+ sum = "h1:JEVoWGNnTF128kNty7T4aG4eqv2z86yiMJPT9Zjp+iw=",
+ version = "v1.15.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_storage",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/storage",
+ sum = "h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_storagetransfer",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/storagetransfer",
+ sum = "h1:5T+PM+3ECU3EY2y9Brv0Sf3oka8pKmsCfpQ07+91G9o=",
+ version = "v1.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_talent",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/talent",
+ sum = "h1:nI9sVZPjMKiO2q3Uu0KhTDVov3Xrlpt63fghP9XjyEM=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_texttospeech",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/texttospeech",
+ sum = "h1:H4g1ULStsbVtalbZGktyzXzw6jP26RjVGYx9RaYjBzc=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_tpu",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/tpu",
+ sum = "h1:/34T6CbSi+kTv5E19Q9zbU/ix8IviInZpzwz3rsFE+A=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_trace",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/trace",
+ sum = "h1:olxC0QHC59zgJVALtgqfD9tGk0lfeCP5/AGXL3Px/no=",
+ version = "v1.9.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_translate",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/translate",
+ sum = "h1:GvLP4oQ4uPdChBmBaUSa/SaZxCdyWELtlAaKzpHsXdA=",
+ version = "v1.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_video",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/video",
+ sum = "h1:upIbnGI0ZgACm58HPjAeBMleW3sl5cT84AbYQ8PWOgM=",
+ version = "v1.15.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_videointelligence",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/videointelligence",
+ sum = "h1:Uh5BdoET8XXqXX2uXIahGb+wTKbLkGH7s4GXR58RrG8=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_vision_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/vision/v2",
+ sum = "h1:8C8RXUJoflCI4yVdqhTy9tRyygSHmp60aP363z23HKg=",
+ version = "v2.7.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_vmmigration",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/vmmigration",
+ sum = "h1:Azs5WKtfOC8pxvkyrDvt7J0/4DYBch0cVbuFfCCFt5k=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_vmwareengine",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/vmwareengine",
+ sum = "h1:b0NBu7S294l0gmtrT0nOJneMYgZapr5x9tVWvgDoVEM=",
+ version = "v0.3.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_vpcaccess",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/vpcaccess",
+ sum = "h1:FOe6CuiQD3BhHJWt7E8QlbBcaIzVRddupwJlp7eqmn4=",
+ version = "v1.6.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_webrisk",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/webrisk",
+ sum = "h1:IY+L2+UwxcVm2zayMAtBhZleecdIFLiC+QJMzgb0kT0=",
+ version = "v1.8.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_websecurityscanner",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/websecurityscanner",
+ sum = "h1:AHC1xmaNMOZtNqxI9Rmm87IJEyPaRkOxeI0gpAacXGk=",
+ version = "v1.5.0",
+ )
+ go_repository(
+ name = "com_google_cloud_go_workflows",
+ build_file_proto_mode = "disable_global",
+ importpath = "cloud.google.com/go/workflows",
+ sum = "h1:FfGp9w0cYnaKZJhUOMqCOJCYT/WlvYBfTQhFWV3sRKI=",
+ version = "v1.10.0",
+ )
+ go_repository(
+ name = "com_shuralyov_dmitri_gpu_mtl",
+ build_file_proto_mode = "disable_global",
+ importpath = "dmitri.shuralyov.com/gpu/mtl",
+ sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=",
+ version = "v0.0.0-20190408044501-666a987793e9",
+ )
+ go_repository(
+ name = "in_gopkg_check_v1",
+ build_file_proto_mode = "disable_global",
+ importpath = "gopkg.in/check.v1",
+ sum = "h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=",
+ version = "v1.0.0-20201130134442-10cb98267c6c",
+ )
+ go_repository(
+ name = "in_gopkg_errgo_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "gopkg.in/errgo.v2",
+ sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=",
+ version = "v2.1.0",
+ )
+ go_repository(
+ name = "in_gopkg_yaml_v2",
+ build_file_proto_mode = "disable_global",
+ importpath = "gopkg.in/yaml.v2",
+ sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=",
+ version = "v2.4.0",
+ )
+ go_repository(
+ name = "in_gopkg_yaml_v3",
+ build_file_proto_mode = "disable_global",
+ importpath = "gopkg.in/yaml.v3",
+ sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=",
+ version = "v3.0.1",
+ )
+ go_repository(
+ name = "io_opencensus_go",
+ build_file_proto_mode = "disable_global",
+ importpath = "go.opencensus.io",
+ sum = "h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=",
+ version = "v0.24.0",
+ )
+ go_repository(
+ name = "io_opencensus_go_contrib_exporter_jaeger",
+ build_file_proto_mode = "disable_global",
+ importpath = "contrib.go.opencensus.io/exporter/jaeger",
+ sum = "h1:yGBYzYMewVL0yO9qqJv3Z5+IRhPdU7e9o/2oKpX4YvI=",
+ version = "v0.2.1",
+ )
+ go_repository(
+ name = "io_rsc_binaryregexp",
+ build_file_proto_mode = "disable_global",
+ importpath = "rsc.io/binaryregexp",
+ sum = "h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=",
+ version = "v0.2.0",
+ )
+ go_repository(
+ name = "io_rsc_quote_v3",
+ build_file_proto_mode = "disable_global",
+ importpath = "rsc.io/quote/v3",
+ sum = "h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=",
+ version = "v3.1.0",
+ )
+ go_repository(
+ name = "io_rsc_sampler",
+ build_file_proto_mode = "disable_global",
+ importpath = "rsc.io/sampler",
+ sum = "h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=",
+ version = "v1.3.0",
+ )
+ go_repository(
+ name = "org_golang_google_api",
+ build_file_proto_mode = "disable_global",
+ importpath = "google.golang.org/api",
+ sum = "h1:t6P9Jj+6XTn4U9I2wycQai6Q/Kz7iOT+QzjJ3G2V4x8=",
+ version = "v0.105.0",
+ )
+ go_repository(
+ name = "org_golang_google_appengine",
+ build_file_proto_mode = "disable_global",
+ importpath = "google.golang.org/appengine",
+ sum = "h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=",
+ version = "v1.6.7",
+ )
+ go_repository(
+ name = "org_golang_google_genproto",
+ build_file_proto_mode = "disable_global",
+ importpath = "google.golang.org/genproto",
+ sum = "h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=",
+ version = "v0.0.0-20230410155749-daa745c078e1",
+ )
+ go_repository(
+ name = "org_golang_google_grpc",
+ build_file_proto_mode = "disable_global",
+ importpath = "google.golang.org/grpc",
+ sum = "h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=",
+ version = "v1.56.3",
+ )
+ go_repository(
+ name = "org_golang_google_grpc_cmd_protoc_gen_go_grpc",
+ build_file_proto_mode = "disable_global",
+ importpath = "google.golang.org/grpc/cmd/protoc-gen-go-grpc",
+ sum = "h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=",
+ version = "v1.3.0",
+ )
+ go_repository(
+ name = "org_golang_google_protobuf",
+ build_file_proto_mode = "disable_global",
+ importpath = "google.golang.org/protobuf",
+ sum = "h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=",
+ version = "v1.32.0",
+ )
+ go_repository(
+ name = "org_golang_x_crypto",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/crypto",
+ sum = "h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=",
+ version = "v0.0.0-20200622213623-75b288015ac9",
+ )
+ go_repository(
+ name = "org_golang_x_exp",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/exp",
+ sum = "h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=",
+ version = "v0.0.0-20200224162631-6cc2880d07d6",
+ )
+ go_repository(
+ name = "org_golang_x_image",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/image",
+ sum = "h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=",
+ version = "v0.0.0-20190802002840-cff245a6509b",
+ )
+ go_repository(
+ name = "org_golang_x_lint",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/lint",
+ sum = "h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=",
+ version = "v0.0.0-20200302205851-738671d3881b",
+ )
+ go_repository(
+ name = "org_golang_x_mobile",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/mobile",
+ sum = "h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=",
+ version = "v0.0.0-20190719004257-d2bd2a29d028",
+ )
+ go_repository(
+ name = "org_golang_x_mod",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/mod",
+ sum = "h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=",
+ version = "v0.14.0",
+ )
+ go_repository(
+ name = "org_golang_x_net",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/net",
+ sum = "h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=",
+ version = "v0.20.0",
+ )
+ go_repository(
+ name = "org_golang_x_oauth2",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/oauth2",
+ sum = "h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=",
+ version = "v0.16.0",
+ )
+ go_repository(
+ name = "org_golang_x_sync",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/sync",
+ sum = "h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=",
+ version = "v0.3.0",
+ )
+ go_repository(
+ name = "org_golang_x_sys",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/sys",
+ sum = "h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=",
+ version = "v0.17.0",
+ )
+ go_repository(
+ name = "org_golang_x_text",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/text",
+ sum = "h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=",
+ version = "v0.14.0",
+ )
+ go_repository(
+ name = "org_golang_x_time",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/time",
+ sum = "h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=",
+ version = "v0.0.0-20191024005414-555d28b269f0",
+ )
+ go_repository(
+ name = "org_golang_x_tools",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/tools",
+ sum = "h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=",
+ version = "v0.15.0",
+ )
+ go_repository(
+ name = "org_golang_x_xerrors",
+ build_file_proto_mode = "disable_global",
+ importpath = "golang.org/x/xerrors",
+ sum = "h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=",
+ version = "v0.0.0-20191204190536-9bdfabe68543",
+ )
diff --git a/docs/Building.md b/docs/Building.md
index 67ebbcf73..c5deaf12a 100644
--- a/docs/Building.md
+++ b/docs/Building.md
@@ -9,16 +9,16 @@ You will need to install a recent Go.
Fetch, build, and install the binary directly with `go get`
-`go install github.com/google/mtail/cmd/mtail`
+`go install github.com/jaqx0r/mtail/cmd/mtail`
NOTE: If you do it this way, you won't have a supported version of `mtail`.
## The "Right Way"
-[Clone](http://github.com/google/mtail) the source from GitHub into your `$GOPATH`. If you don't have a `$GOPATH`, see the next section.
+[Clone](http://github.com/jaqx0r/mtail) the source from GitHub into your `$GOPATH`. If you don't have a `$GOPATH`, see the next section.
```
-git clone https://github.com/google/mtail
+git clone https://github.com/jaqx0r/mtail
cd mtail
make test install
```
@@ -35,7 +35,7 @@ The unit tests can be run with `make test`, which invokes `go test`. The slower
### Cross-compilation
-`goreleaser` is used to build the binaries available for download on the Releases page. If yuo want to build your own locally, fetch goreleaser and update the config file locally if necessary.
+`goreleaser` is used to build the binaries available for download on the Releases page. If you want to build your own locally, fetch goreleaser and update the config file locally if necessary.
## No Go
diff --git a/docs/Interoperability.md b/docs/Interoperability.md
index 9bd09b573..2deef0248 100644
--- a/docs/Interoperability.md
+++ b/docs/Interoperability.md
@@ -42,7 +42,7 @@ TODO(jaq): Instead, mtail will export a histogram of the runtime per line of eac
# Log Collection, Distribution, and Filtering {: #syslog}
-`mtail` is not intended to be used as a replacement for `syslogd`. `mtail` can read from named pipes and unix domain sockets on systems that support them, but the intent is that a proper `syslogd` can manage the collection of those logs, filter out interestnig ones if necessary, and forward them to `mtail` via a named pipe.
+`mtail` is not intended to be used as a replacement for `syslogd`. `mtail` can read from named pipes and unix domain sockets on systems that support them, but the intent is that a proper `syslogd` can manage the collection of those logs, filter out interesting ones if necessary, and forward them to `mtail` via a named pipe.
Both `rsyslogd` and `syslog-ng` are possible choices here.
diff --git a/docs/Programming-Guide.md b/docs/Programming-Guide.md
index 2a7d62a9d..e9f556590 100644
--- a/docs/Programming-Guide.md
+++ b/docs/Programming-Guide.md
@@ -132,6 +132,18 @@ parsing:
Note the position of the underscore in the regular expression match.
+## Log Filtering
+
+The `log_filter` keyword can be used in an mtail program to provide a list of filenames (including the full path to the file). If a `log_filter` is used the program is restricted only to processing logfiles with the names provided. If no `log_filter` keyword is used then all logfiles read by mtail are read by the program. `log_filter` can be used to reduce the resource consumption of mtail by ensuring programs only read the lines they were designed for. `log_filter` lists are additive if the keyword is used multiple times and duplicate logfile entries are ignored.
+
+Example use:
+
+```
+log_filter "/tmp/read_this_log.txt", "/tmp/read_this_log_as_well.txt"
+...
+log_filter "/tmp/and_yet_another_log.txt"
+```
+
## Conditional structures
The `/pattern/ { action }` idiom is the normal conditional control flow
@@ -184,6 +196,40 @@ operator, or to negate the match the `!~`, like so:
}
```
+### Chaining match conditions
+
+Multiple patterns can be combined in a single condition using the `&&` and `||`
+logical operators. This is useful for filtering log lines based on both the
+filename and the line content:
+
+```mtail
+getfilename() =~ /apache/ && /HTTP\/1\.1/ {
+ apache_http11_requests++
+}
+```
+
+Both patterns are tried in order (left to right), and the condition short
+circuits as normal for `&&` and `||`.
+
+When multiple patterns appear in the same condition, each registers its capture
+group references (such as `$0`, `$1`, etc.) in the same scope. The capture
+group references after the condition refer to the *last* executed match,
+consistent with the runtime order of evaluation:
+
+```mtail
+const PAT /n/
+/(?P\w+)/ && PAT {
+ # $0 refers to PAT's match, not the first pattern's match.
+ # Use named capture groups if you need the first pattern's captures:
+ # $word still refers to the \w+ capture group from the first pattern.
+}
+```
+
+This is known as *last pattern match wins* semantics. `mtail` will emit a
+notice when numbered capture group bindings are updated in a chained match
+expression. Use named capture groups for unambiguous references when chaining
+patterns.
+
## Storing intermediate state
Hidden metrics are metrics that can be used for internal state and are never
@@ -400,8 +446,20 @@ counter total
}
```
-`mtail` does not presently have a way to test if a capture group is defined or
-not.
+Use the `defined()` builtin to test if a capture group was matched:
+
+```
+counter total
+
+/^[a-z]+ ((?P\d+)|-)$/ {
+ defined($response_size) {
+ total = $response_size
+ }
+}
+```
+
+`defined()` takes a capture group reference and returns true if it was
+matched in the current line.
## Parsing numbers with extra characters
diff --git a/docs/Testing.md b/docs/Testing.md
index 898beae13..84392f505 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -5,7 +5,7 @@
By default any compile errors are logged to the standard log `/tmp/mtail.INFO`
unless otherwise redirected. (You can emit to standard out with
`--logtostderr` flag.) Program errors are also printed on the HTTP status
-handler, by default at porrt 3903.
+handler, by default at port 3903.
If you want more debugging information, `mtail` provides a few flags to assist with testing your program in standalone mode.
@@ -40,7 +40,7 @@ mtail --one_shot --progs ./progs --logs testdata/foo.log
If you wish, send a PR containing your program, some sample input, and a golden
output to be run as a test in
-http://github.com/google/mtail/blob/main/ex_test.go to ensure that mtail
+http://github.com/jaqx0r/mtail/blob/main/ex_test.go to ensure that mtail
never breaks your program (or that your program gets any updates if the
language changes.)
diff --git a/docs/Troubleshooting.md b/docs/Troubleshooting.md
index a0d7a7105..d30c9d31f 100644
--- a/docs/Troubleshooting.md
+++ b/docs/Troubleshooting.md
@@ -14,19 +14,19 @@ Please when reporting a problem, include the `mtail` version:
## `go get` or build problems
-### `package github.com/google/mtail: no Go files`
+### `package github.com/jaqx0r/mtail: no Go files`
You're using go 1.11 or higher, which now starts to use go modules, and doesn't like source code layouts like `mtail` which doesn't have any Go files in the top directory.
Either set `GO111MODULE=on` environment variable first, or `go get` the binary directly:
-`go get github.com/google/mtail/cmd/mtail`
+`go get github.com/jaqx0r/mtail/cmd/mtail`
vs
```
-GO111MODULE=on go get -u github.com/google/mtail
-cd $GOPATH/src/github.com/google/mtail
+GO111MODULE=on go get -u github.com/jaqx0r/mtail
+cd $GOPATH/src/github.com/jaqx0r/mtail
make install
```
@@ -73,20 +73,20 @@ or a memory profile:
There are many good guides on using the profiling tool:
- * https://software.intel.com/en-us/blogs/2014/05/10/debugging-performance-issues-in-go-programs is one such guide.
+* https://software.intel.com/en-us/blogs/2014/05/10/debugging-performance-issues-in-go-programs is one such guide.
The goroutine stack dump can also help explain what is happening at the moment.
http://localhost:3903/debug/pprof/goroutine?debug=2 shows the full goroutine stack dump.
- * `(*Watcher).readEvents` reads events from the filesystem
- * `(*Tailer).run` processes log change events; `.read` reads the latest log lines
- * `(*Loader).processEvents` handles filesystem event changes regarding new program text
- * `(*Loader).processLines` handles new lines coming from the log tailer
- * `(*MtailServer).WaitForShutdown` waits for the other components to terminate
- * `(*Exporter).StartMetricPush` exists if there are any push collectors (e.g. Graphite) to push to
- * `(*Exporter).HandlePrometheusMetrics` exists if an existing Prometheus pull collection is going on
+* `(*Watcher).readEvents` reads events from the filesystem
+* `(*Tailer).run` processes log change events; `.read` reads the latest log lines
+* `(*Loader).processEvents` handles filesystem event changes regarding new program text
+* `(*Loader).processLines` handles new lines coming from the log tailer
+* `(*MtailServer).WaitForShutdown` waits for the other components to terminate
+* `(*Exporter).StartMetricPush` exists if there are any push collectors (e.g. Graphite) to push to
+* `(*Exporter).HandlePrometheusMetrics` exists if an existing Prometheus pull collection is going on
There is one `(*VM).Run` stack per program. These are opaque to the goroutine
stack dump as they execute the bytecode. However, the second argument to `Run`
@@ -95,11 +95,73 @@ You can transcode these back to their names by doing a conversion from the
int32 value in hex provided in the stack, e.g.: 0x61706163 -> 'apac' (probably
an apache log program); 0x7273796e -> 'rsyn' (probably an rsyncd log program)
-Obvious problems seen in the goroutine stack dump are long-waiting gorotines, usually on mutexes.
+Obvious problems seen in the goroutine stack dump are long-waiting goroutines, usually on mutexes.
(they show their block time in minutes, e.g. `goroutine 38 [semacquire, 1580
minutes]:`) which usually also manifest as a logjam (no pun intended) in the
loader, tailer, and watcher goroutines (in state 'chan send').
+### Simulating production for memory profiling
+
+To analyse memory allocations under realistic load:
+
+1. Build mtail:
+ ```
+ bazel build //cmd/mtail
+ ```
+
+2. Start mtail with example programs and a temporary log file:
+ ```
+ touch /tmp/mtail_pprof_log
+ bazel-bin/cmd/mtail/mtail_/mtail \
+ --progs examples/ \
+ --logs /tmp/mtail_pprof_log \
+ --poll_interval 50ms \
+ --logtostderr \
+ --stderrthreshold 0 &
+ ```
+
+3. Feed test log data in a loop to simulate continuous traffic:
+ ```
+ while true; do
+ cat internal/mtail/testdata/*.log >> /tmp/mtail_pprof_log
+ sleep 6
+ done &
+ ```
+
+4. Capture an allocation profile with `go tool pprof`:
+ ```
+ go tool pprof -alloc_space -top \
+ http://localhost:3903/debug/pprof/allocs
+ ```
+ Use `-seconds 30` for a delta profile (allocations within a 30 s window),
+ or omit it for a cumulative profile since process start.
+
+5. Drill into specific functions:
+ ```
+ go tool pprof -alloc_space -list 'ProcessLogLine' \
+ http://localhost:3903/debug/pprof/allocs
+ go tool pprof -alloc_space -peek 'execute' \
+ http://localhost:3903/debug/pprof/allocs
+ ```
+
+### Known allocation hot spots
+
+As of v3.2.52, the cumulative `alloc_space` profile shows that roughly 60 % of
+heap allocations occur on the per-log-line hot path in `ProcessLogLine` and
+`execute` (`internal/runtime/vm/vm.go`).
+
+| Function | Flat alloc | Key lines |
+|---|---|---|
+| `VM.ProcessLogLine` | ~28 % | `v.t = new(thread)` (4.5 MB) β new thread per line; `t.matches = make(...)` (12.5 MB) β match map per line |
+| `VM.execute` | ~17 % | `t.matches[index] = v.re[index].FindStringSubmatch(...)` (7 MB) β regex submatch allocations inside `code.Match` |
+| `Runtime.CompileAndRun` | ~9 % | One-shot startup cost from program loading, parsing, type checking, and code generation |
+
+The single biggest allocation is `t.matches = make(map[int][]string, len(v.re))`
+in `ProcessLogLine`: a pre-sized map to hold regex capture group results,
+recreated from scratch on every log line. An object pool (`sync.Pool`) for
+`thread` structs and their match maps would eliminate the bulk of hot-path
+allocations.
+
## Distributed Tracing
`mtail` can export traces to the [Jaeger](https://www.jaegertracing.io/) trace collector. Specify the Jaeger endpoint with the `--jaeger_endpoint` flag
diff --git a/docs/debugging.md b/docs/debugging.md
index 25ba51618..53807b26f 100644
--- a/docs/debugging.md
+++ b/docs/debugging.md
@@ -32,9 +32,9 @@ error recovery pops state 2
error recovery pops state 0
```
-This log says the lexer sent a LSQUARE token, and the parser was in state 14 when it saw it. The snippet below from `y.output` indicates state 14 is never expecting a LSQUARE, and the following lnies in the log above show the state stack being popped -- 0, 2, 14, 49, 102, 14.
+This log says the lexer sent a LSQUARE token, and the parser was in state 14 when it saw it. The snippet below from `y.output` indicates state 14 is never expecting a LSQUARE, and the following lines in the log above show the state stack being popped -- 0, 2, 14, 49, 102, 14.
-Walking backwards from state 0 (`$start`), we can get a list of nonterminal names to put in the state machine match expression used in the `%error` directive, and fill in the gaps with our knowledge of the intermediate states in our parose tree.
+Walking backwards from state 0 (`$start`), we can get a list of nonterminal names to put in the state machine match expression used in the `%error` directive, and fill in the gaps with our knowledge of the intermediate states in our parse tree.
`y.output`:
```
@@ -99,7 +99,7 @@ The formatted mtail program should help make it obvious what's happening and let
Once we have the smallest program we can add it to the crash corpus in [`internal/runtime/fuzz/`](../internal/runtime/fuzz/) and running `make fuzz` should run and fail on it straight away.
-Or, variants of the program can be added to the various `*Invalid` tests in parts of the `vm` module, e.g. [`parser_test.go`](../internal/runtime/compiler/parser/parser_test.go) or [`checker_test.go`](../internal/runtime/compiler/checker/checker_test.go) depending on where in the compiler the defect is occuring.
+Or, variants of the program can be added to the various `*Invalid` tests in parts of the `vm` module, e.g. [`parser_test.go`](../internal/runtime/compiler/parser/parser_test.go) or [`checker_test.go`](../internal/runtime/compiler/checker/checker_test.go) depending on where in the compiler the defect is occurring.
If the crash is in `vm.go` then we can dump the program to see what AST and types, and bytecode it generates.
diff --git a/docs/faq.md b/docs/faq.md
index b86f7002e..de608abbc 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -92,6 +92,6 @@ overall gain.
`mtail` will reload programme files when it receives a `SIGHUP` signal.
-It's assumed that programmes do not change very often, so it relies on an external trigger rather than spend resourecs of its own polling for changes at all. `inotify` is not used either, as programme reloads would be the only use of that library, and the benefit does not seem worth the cost of including the extra dependency.
+It's assumed that programmes do not change very often, so it relies on an external trigger rather than spend resources of its own polling for changes at all. `inotify` is not used either, as programme reloads would be the only use of that library, and the benefit does not seem worth the cost of including the extra dependency.
See the [Deployment](Deployment.md) guide for suggestions for "automatic" programme reloads.
diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel
new file mode 100644
index 000000000..b8136b230
--- /dev/null
+++ b/examples/BUILD.bazel
@@ -0,0 +1,5 @@
+filegroup(
+ name = "examples",
+ srcs = glob(["*.mtail"]),
+ visibility = ["//internal/mtail:__subpackages__"],
+)
diff --git a/examples/lighttpd.mtail b/examples/lighttpd.mtail
index e79e38a93..80967bee7 100644
--- a/examples/lighttpd.mtail
+++ b/examples/lighttpd.mtail
@@ -10,7 +10,7 @@ counter bytes_in by status
counter requests by proxy_cache
-const ACCESSLOG_RE // +
+const ACCESSLOG_RE
/(?P\S+) (?P\S+) (?P\S+)/ +
/ \[(?P[^\]]+)\] "(?P\S+) (?P.+?) / +
/(?P\S+)" (?P\d+) (?P\d+) (?P\d+)/ +
@@ -20,7 +20,7 @@ const ACCESSLOG_RE // +
# /var/log/lighttpd/access.log
getfilename() =~ /lighttpd.access.log/ {
- // + ACCESSLOG_RE {
+ ACCESSLOG_RE {
# Parse an accesslog entry.
$url == "/healthz" {
# nothing
diff --git a/examples/log_filter.mtail b/examples/log_filter.mtail
new file mode 100644
index 000000000..def7365c4
--- /dev/null
+++ b/examples/log_filter.mtail
@@ -0,0 +1,10 @@
+# Copyright 2025 The mtail Authors. All Rights Reserved.
+# This file is available under the Apache license.
+# SPDX-License-Identifier: Apache-2.0
+
+log_filter "<>"
+counter lines_total
+
+/$/ {
+ lines_total++
+}
diff --git a/examples/log_filter_ignore.mtail b/examples/log_filter_ignore.mtail
new file mode 100644
index 000000000..63bdd02cd
--- /dev/null
+++ b/examples/log_filter_ignore.mtail
@@ -0,0 +1,10 @@
+# Copyright 2025 The mtail Authors. All Rights Reserved.
+# This file is available under the Apache license.
+# SPDX-License-Identifier: Apache-2.0
+
+log_filter "do_not_read_this_log"
+counter lines_total
+
+/$/ {
+ lines_total++
+}
diff --git a/examples/mysql_slowqueries.mtail b/examples/mysql_slowqueries.mtail
index 1cad0f283..20d5b712e 100644
--- a/examples/mysql_slowqueries.mtail
+++ b/examples/mysql_slowqueries.mtail
@@ -50,7 +50,7 @@ const END_QUERY_LINE /.*;$/
settime(time)
-// + USER_HOST {
+USER_HOST {
user = $1
host = $2
}
@@ -59,7 +59,7 @@ user == "" {
stop
}
-// + QUERY_TIME {
+QUERY_TIME {
tmp_query_time = $1
tmp_lock_time = $2
query_time_overall_sum += tmp_query_time
@@ -68,7 +68,7 @@ user == "" {
lock_time_total_count++
}
-// + FULL_QUERY_LINE {
+FULL_QUERY_LINE {
# We should have everything we need now.
query_type = tolower($1)
service = $2
@@ -76,7 +76,7 @@ user == "" {
lock_time[query_type, host, service, user] += tmp_lock_time
}
-// + UNINSTRUMENTED_QUERY_LINE {
+UNINSTRUMENTED_QUERY_LINE {
# We should have everything we need now.
query_type = tolower($1)
service = "n/a"
@@ -84,12 +84,12 @@ user == "" {
lock_time[query_type, host, service, user] += tmp_lock_time
}
-// + PARTIAL_QUERY_LINE {
+PARTIAL_QUERY_LINE {
query_type = tolower($1)
partial = 1
}
-// + END_QUERY_LINE && partial == 1 {
+END_QUERY_LINE && partial == 1 {
partial = 0
/.*# (.*)$/ {
service = $1
diff --git a/examples/postfix.mtail b/examples/postfix.mtail
index 3fc265816..13883a7d8 100644
--- a/examples/postfix.mtail
+++ b/examples/postfix.mtail
@@ -42,7 +42,7 @@ const QMGR_REMOVE_LINE /: removed$/
# buckets: 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3
$application == "lmtp" {
- // + DELIVERY_DELAY_LINE {
+ DELIVERY_DELAY_LINE {
# 1st field: before_queue_manager
postfix_lmtp_delivery_delay_seconds["before_queue_manager"] = $bqm
@@ -62,7 +62,7 @@ const QMGR_REMOVE_LINE /: removed$/
# buckets: 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3
$application == "pipe" {
- // + DELIVERY_DELAY_LINE {
+ DELIVERY_DELAY_LINE {
# 1st field: before_queue_manager
postfix_pipe_delivery_delay_seconds[$relay]["before_queue_manager"] = $bqm
@@ -89,11 +89,11 @@ const QMGR_REMOVE_LINE /: removed$/
counter postfix_qmgr_messages_removed_total
$application == "qmgr" {
- // + QMGR_INSERT_LINE {
+ QMGR_INSERT_LINE {
postfix_qmgr_messages_inserted_recipients = $nrcpt
postfix_qmgr_messages_inserted_size_bytes = $size
}
- // + QMGR_REMOVE_LINE {
+ QMGR_REMOVE_LINE {
postfix_qmgr_messages_removed_total++
}
}
@@ -106,7 +106,7 @@ const QMGR_REMOVE_LINE /: removed$/
counter postfix_smtp_tls_connections_total by trust, protocol, cipher, secret_bits, algorithm_bits
$application == "smtp" {
- // + DELIVERY_DELAY_LINE {
+ DELIVERY_DELAY_LINE {
# 1st field: before_queue_manager
postfix_smtp_delivery_delay_seconds["before_queue_manager"] = $bqm
@@ -120,7 +120,7 @@ const QMGR_REMOVE_LINE /: removed$/
postfix_smtp_delivery_delay_seconds["transmission"] = $tx
}
- // + SMTP_TLS_LINE {
+ SMTP_TLS_LINE {
postfix_smtp_tls_connections_total[$1][$2][$3][$4][$5]++
}
}
@@ -175,7 +175,7 @@ const QMGR_REMOVE_LINE /: removed$/
/warning: \S+: SASL \S+ authentication failed: / {
postfix_smtpd_sasl_authentication_failures_total++
}
- // + SMTPD_TLS_LINE {
+ SMTPD_TLS_LINE {
postfix_smtpd_tls_connections_total[$1][$2][$3][$4][$5]++
}
}
diff --git a/examples/vsftpd.mtail b/examples/vsftpd.mtail
index 66f91059d..3a4f603e5 100644
--- a/examples/vsftpd.mtail
+++ b/examples/vsftpd.mtail
@@ -27,7 +27,7 @@ def vsftpd_timestamp {
}
}
-const XFERLOG_RE // +
+const XFERLOG_RE
# e.g. 1 172.18.115.36 528
# time spent transferring
/\s(?P\d+)/ +
@@ -57,7 +57,7 @@ const XFERLOG_RE // +
# completion status
/\s(?P\S)/
-const VSFTPD_LOG_RE // +
+const VSFTPD_LOG_RE
/ \[pid \d+\]/ +
/( \[\w+\])?/ +
/ (?PCONNECT|OK LOGIN|OK UPLOAD|FTP (command|response)):/ +
@@ -70,7 +70,7 @@ const PAYLOAD_COMMAND_RE /^"(\w{4})[" -]/
@vsftpd_timestamp {
getfilename() =~ /xferlog/ {
- // + XFERLOG_RE {
+ XFERLOG_RE {
# Handles log entries from the wuftpd format xferlog.
$direction == "i" {
direction = "incoming"
@@ -87,7 +87,7 @@ const PAYLOAD_COMMAND_RE /^"(\w{4})[" -]/
}
getfilename() =~ /vsftpd.log/ {
- // + VSFTPD_LOG_RE {
+ VSFTPD_LOG_RE {
# Handle vsftpd.log log file."""
$command == "CONNECT" {
sessions[$client] = timestamp()
@@ -101,7 +101,7 @@ const PAYLOAD_COMMAND_RE /^"(\w{4})[" -]/
uploads++
}
$command == "FTP command" {
- $payload =~ // + PAYLOAD_COMMAND_RE {
+ $payload =~ PAYLOAD_COMMAND_RE {
commands[$1]++
$1 == "QUIT" {
@@ -111,7 +111,7 @@ const PAYLOAD_COMMAND_RE /^"(\w{4})[" -]/
}
}
$command == "FTP response" {
- $payload =~ // + PAYLOAD_RESPONSE_RE {
+ $payload =~ PAYLOAD_RESPONSE_RE {
responses[$1]++
}
}
diff --git a/go.mod b/go.mod
index 3ffe06257..0de349677 100644
--- a/go.mod
+++ b/go.mod
@@ -1,32 +1,50 @@
-module github.com/google/mtail
+module github.com/jaqx0r/mtail
-go 1.21.1
+go 1.25.0
+
+toolchain go1.26.4
require (
contrib.go.opencensus.io/exporter/jaeger v0.2.1
- github.com/golang/glog v1.2.2
- github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
- github.com/google/go-cmp v0.6.0
+ github.com/bazelbuild/rules_go v0.61.0
+ github.com/golang/glog v1.2.5
+ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8
+ github.com/google/go-cmp v0.7.0
github.com/pkg/errors v0.9.1
- github.com/prometheus/client_golang v1.20.4
- github.com/prometheus/common v0.60.0
+ github.com/prometheus/client_golang v1.23.2
+ github.com/prometheus/common v0.68.1
go.opencensus.io v0.24.0
- golang.org/x/sys v0.26.0
+ go.opentelemetry.io/otel v1.44.0
+ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0
+ go.opentelemetry.io/otel/sdk v1.44.0
+ go.opentelemetry.io/otel/sdk/metric v1.44.0
+ golang.org/x/sys v0.45.0
+ golang.org/x/tools v0.45.0
)
require (
github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/klauspost/compress v1.17.9 // indirect
+ github.com/go-logr/logr v1.4.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
- github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/procfs v0.15.1 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect
- golang.org/x/sync v0.7.0 // indirect
+ go.opentelemetry.io/auto/sdk v1.2.1 // indirect
+ go.opentelemetry.io/otel/metric v1.44.0 // indirect
+ go.opentelemetry.io/otel/trace v1.44.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.10.0 // indirect
+ golang.org/x/net v0.55.0 // indirect
+ golang.org/x/sync v0.20.0 // indirect
+ golang.org/x/text v0.37.0 // indirect
google.golang.org/api v0.105.0 // indirect
- google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
- google.golang.org/grpc v1.56.3 // indirect
- google.golang.org/protobuf v1.34.2 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
+ google.golang.org/grpc v1.81.1 // indirect
+ google.golang.org/protobuf v1.36.11 // indirect
)
diff --git a/go.sum b/go.sum
index ef3523c74..3b32e270e 100644
--- a/go.sum
+++ b/go.sum
@@ -25,8 +25,12 @@ contrib.go.opencensus.io/exporter/jaeger v0.2.1/go.mod h1:Y8IsLgdxqh1QxYxPC5IgXV
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/bazelbuild/rules_go v0.61.0 h1:Anz8trQHMdiCIjUzSjqL1JEZRFZZMYzKkIqwT7ESaMI=
+github.com/bazelbuild/rules_go v0.61.0/go.mod h1:6YghDRf6l3FSiAwncK+Ww9jE1naoQzNq28gaKJeB67I=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
+github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -45,14 +49,19 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
-github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
+github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I=
+github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -70,9 +79,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -81,9 +89,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@@ -92,16 +99,20 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
-github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -113,15 +124,15 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
-github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
+github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
-github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
-github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
-github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
-github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.68.1 h1:omjRRl4QP4komogpXuhfeOiisQg7xdy8VM1UY+pStaY=
+github.com/prometheus/common v0.68.1/go.mod h1:ZzL3f6u94qUxh9p+tJTrF+FvBS1XXbbRAZCQkytAL0Y=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -130,8 +141,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=
github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -142,6 +153,28 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
+go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
+go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0 h1:SUplec5dp06reu1zaXmOXdvqH398taqrDXqUl99jxSc=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0/go.mod h1:ho2g4N+ane+swq5I/VBkKWnRDY4kUINH3FuqyZqX/Ug=
+go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
+go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
+go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA=
+go.opentelemetry.io/otel/metric/x v0.66.0/go.mod h1:d1+BDj9t96do0/1LoU1ayfCv79ZgNE41qbhBvnMOBZk=
+go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
+go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
+go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
+go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
+go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
+go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
+go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
+go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
+go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -194,8 +227,8 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
-golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
+golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
+golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -209,8 +242,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -231,15 +264,15 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
+golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
-golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
+golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -273,9 +306,13 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
+golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
+gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -313,8 +350,10 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
+google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -325,8 +364,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
-google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
+google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -336,10 +375,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
-google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
diff --git a/hooks/build b/hooks/build
deleted file mode 100755
index 6325668f0..000000000
--- a/hooks/build
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-# $IMAGE_NAME var is injected into the build so the tag is correct.
-echo "Build hook running"
-
-docker build \
- --build-arg version=$(git describe --tags --always) \
- --build-arg commit_hash=$(git rev-parse HEAD) \
- --build-arg vcs_url=$(git config --get remote.origin.url) \
- --build-arg vcs_branch=$(git rev-parse --abbrev-ref HEAD) \
- --build-arg build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
- -t $IMAGE_NAME .
diff --git a/hooks/post_checkout b/hooks/post_checkout
deleted file mode 100755
index 69644b577..000000000
--- a/hooks/post_checkout
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-echo "Unshallowing to get correct tags to work."
-git fetch --tags --unshallow --quiet origin
diff --git a/hooks/post_push b/hooks/post_push
deleted file mode 100755
index 4d63ceb33..000000000
--- a/hooks/post_push
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-# hooks/post_push
-
-# https://docs.docker.com/docker-cloud/builds/advanced/
-# https://semver.org/
-
-function add_tag() {
- echo "Adding tag ${1}"
- docker tag $IMAGE_NAME $DOCKER_REPO:$1
- docker push $DOCKER_REPO:$1
-}
-
-TAG=`git describe --tag --match "v*"`
-
-MAJOR=`echo ${TAG} | awk -F'-' '{print $1}' | awk -F'.' '{print $1}' | sed 's/v//'`
-MINOR=`echo ${TAG} | awk -F'-' '{print $1}' | awk -F'.' '{print $2}' | sed 's/v//'`
-PATCH=`echo ${TAG} | awk -F'-' '{print $1}' | awk -F'.' '{print $3}' | sed 's/v//'`
-PRLS=`echo ${TAG} | awk -F'-' '{print $2}'`
-
-num='^[0-9]+$'
-pre='^[0-9A-Za-z\.]+$'
-
-echo "Current Build: ${TAG}"
-
-if [ ! -z $MAJOR ] && [[ $MAJOR =~ $num ]]; then
- add_tag ${MAJOR}
-
- if [ ! -z $MINOR ] && [[ $MINOR =~ $num ]]; then
- add_tag ${MAJOR}.${MINOR}
-
- if [ ! -z $PATCH ] && [[ $PATCH =~ $num ]]; then
- add_tag ${MAJOR}.${MINOR}.${PATCH}
-
- if [ ! -z $PRLS ] && [[ ! $PRLS =~ $num ]] && [[ $PRLS =~ $pre ]]; then
- add_tag ${MAJOR}.${MINOR}.${PATCH}-${PRLS}
- fi
- fi
- fi
-fi
-
-exit $?
diff --git a/internal/exporter/BUILD.bazel b/internal/exporter/BUILD.bazel
new file mode 100644
index 000000000..058cf6b40
--- /dev/null
+++ b/internal/exporter/BUILD.bazel
@@ -0,0 +1,56 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "exporter",
+ srcs = [
+ "collectd.go",
+ "export.go",
+ "graphite.go",
+ "json.go",
+ "otel.go",
+ "prometheus.go",
+ "statsd.go",
+ "varz.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/exporter",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "@com_github_golang_glog//:glog",
+ "@com_github_pkg_errors//:errors",
+ "@com_github_prometheus_client_golang//prometheus",
+ "@com_github_prometheus_common//expfmt",
+ "@io_opentelemetry_go_otel//:otel",
+ "@io_opentelemetry_go_otel//attribute",
+ "@io_opentelemetry_go_otel_exporters_otlp_otlpmetric_otlpmetricgrpc//:otlpmetricgrpc",
+ "@io_opentelemetry_go_otel_sdk//instrumentation",
+ "@io_opentelemetry_go_otel_sdk//resource",
+ "@io_opentelemetry_go_otel_sdk_metric//:metric",
+ "@io_opentelemetry_go_otel_sdk_metric//metricdata",
+ ],
+)
+
+go_test(
+ name = "exporter_test",
+ size = "small",
+ srcs = [
+ "export_test.go",
+ "graphite_test.go",
+ "json_test.go",
+ "otel_test.go",
+ "prometheus_test.go",
+ "varz_test.go",
+ ],
+ embed = [":exporter"],
+ deps = [
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/testutil",
+ "@com_github_prometheus_client_golang//prometheus/testutil",
+ "@io_opentelemetry_go_otel//attribute",
+ "@io_opentelemetry_go_otel_sdk//instrumentation",
+ "@io_opentelemetry_go_otel_sdk_metric//metricdata",
+ "@io_opentelemetry_go_otel_sdk_metric//metricdata/metricdatatest",
+ ],
+)
diff --git a/internal/exporter/collectd.go b/internal/exporter/collectd.go
index 651b82f58..f25800abb 100644
--- a/internal/exporter/collectd.go
+++ b/internal/exporter/collectd.go
@@ -10,7 +10,7 @@ import (
"strings"
"time"
- "github.com/google/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics"
)
const (
diff --git a/internal/exporter/export.go b/internal/exporter/export.go
index 1825974fd..12c604f1a 100644
--- a/internal/exporter/export.go
+++ b/internal/exporter/export.go
@@ -19,13 +19,14 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics"
"github.com/pkg/errors"
)
// Commandline Flags.
var (
- writeDeadline = flag.Duration("metric_push_write_deadline", 10*time.Second, "Time to wait for a push to succeed before exiting with an error.")
+ writeDeadline = flag.Duration("metric_push_write_deadline", 10*time.Second, "Time to wait for a push to succeed before exiting with an error.")
+ enableOpenTelemetry = flag.Bool("experimental_enable_opentelemetry", false, "Enable the experimental Open Telemetry metric pusher.")
)
// Exporter manages the export of metrics to passive and active collectors.
@@ -36,6 +37,7 @@ type Exporter struct {
store *metrics.Store
pushInterval time.Duration
hostname string
+ version string
omitProgLabel bool
emitTimestamp bool
exportDisabled bool
@@ -55,6 +57,14 @@ func Hostname(hostname string) Option {
}
}
+// Version specifies the mtail version to use in exported metrics.
+func Version(version string) Option {
+ return func(e *Exporter) error {
+ e.version = version
+ return nil
+ }
+}
+
// OmitProgLabel sets the Exporter to not put program names in metric labels.
func OmitProgLabel() Option {
return func(e *Exporter) error {
@@ -123,6 +133,12 @@ func New(ctx context.Context, store *metrics.Store, options ...Option) (*Exporte
o := pushOptions{"udp", *statsdHostPort, metricToStatsd, statsdExportTotal, statsdExportSuccess}
e.RegisterPushExport(o)
}
+ if *enableOpenTelemetry {
+ err := e.InitOtel(ctx)
+ if err != nil {
+ return nil, err
+ }
+ }
e.StartMetricPush()
// This routine manages shutdown of the Exporter.
@@ -183,6 +199,9 @@ type formatter func(string, *metrics.Metric, *metrics.LabelSet, time.Duration) s
func (e *Exporter) writeSocketMetrics(c io.Writer, f formatter, exportTotal *expvar.Int, exportSuccess *expvar.Int) error {
return e.store.Range(func(m *metrics.Metric) error {
+ if m.Hidden {
+ return nil
+ }
m.RLock()
// Don't try to send text metrics to any push service.
if m.Kind == metrics.Text {
diff --git a/internal/exporter/export_test.go b/internal/exporter/export_test.go
index 317cbba06..480aef1cd 100644
--- a/internal/exporter/export_test.go
+++ b/internal/exporter/export_test.go
@@ -12,9 +12,9 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
const prefix = "prefix"
@@ -130,7 +130,7 @@ func TestMetricToGraphite(t *testing.T) {
testutil.ExpectNoDiff(t, expected, r)
histogramMetric := metrics.NewMetric("hist", "prog", metrics.Histogram, metrics.Buckets, "xxx")
- lv := &metrics.LabelValue{Labels: []string{"bar"}, Value: datum.MakeBuckets([]datum.Range{{0, 10}, {10, 20}}, time.Unix(0, 0))}
+ lv := &metrics.LabelValue{Labels: []string{"bar"}, Value: datum.MakeBuckets([]datum.Range{{Min: 0, Max: 10}, {Min: 10, Max: 20}}, time.Unix(0, 0))}
histogramMetric.AppendLabelValue(lv)
d, _ = histogramMetric.GetDatum("bar")
datum.SetFloat(d, 1, ts)
diff --git a/internal/exporter/graphite.go b/internal/exporter/graphite.go
index 74df6cc9c..a916eb94d 100644
--- a/internal/exporter/graphite.go
+++ b/internal/exporter/graphite.go
@@ -12,8 +12,8 @@ import (
"strings"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
)
var (
@@ -35,6 +35,9 @@ func (e *Exporter) HandleGraphite(w http.ResponseWriter, r *http.Request) {
return r.Context().Err()
default:
}
+ if m.Hidden {
+ return nil
+ }
m.RLock()
graphiteExportTotal.Add(1)
lc := make(chan *metrics.LabelSet)
diff --git a/internal/exporter/graphite_test.go b/internal/exporter/graphite_test.go
index b39cdf97d..48b81c21a 100644
--- a/internal/exporter/graphite_test.go
+++ b/internal/exporter/graphite_test.go
@@ -12,9 +12,9 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var handleGraphiteTests = []struct {
diff --git a/internal/exporter/json_test.go b/internal/exporter/json_test.go
index 3235f870f..a386c9017 100644
--- a/internal/exporter/json_test.go
+++ b/internal/exporter/json_test.go
@@ -13,9 +13,9 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var handleJSONTests = []struct {
diff --git a/internal/exporter/otel.go b/internal/exporter/otel.go
new file mode 100644
index 000000000..e96ae4d95
--- /dev/null
+++ b/internal/exporter/otel.go
@@ -0,0 +1,231 @@
+// Copyright 2025 The mtail Authors. All Rights Reserved
+// This file is available under the Apache license.
+
+package exporter
+
+import (
+ "context"
+ "fmt"
+ "maps"
+ "math"
+ "slices"
+ "time"
+
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "go.opentelemetry.io/otel"
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
+ "go.opentelemetry.io/otel/sdk/instrumentation"
+ "go.opentelemetry.io/otel/sdk/metric"
+ "go.opentelemetry.io/otel/sdk/metric/metricdata"
+ "go.opentelemetry.io/otel/sdk/resource"
+)
+
+var processStartTime = time.Now()
+
+// Produce implements the opentelemetry Producer.Produce method.
+func (e *Exporter) Produce(context.Context) ([]metricdata.ScopeMetrics, error) {
+ scopedOtelMetrics := make(map[string][]metricdata.Metrics)
+
+ e.store.Range(func(m *metrics.Metric) error {
+ if m.Hidden {
+ return nil
+ }
+ m.RLock()
+ defer m.RUnlock()
+
+ newMetric := metricdata.Metrics{
+ Name: m.Name,
+ Description: fmt.Sprintf("%s defined at %s", m.Name, m.Source),
+ }
+ switch m.Kind {
+ case metrics.Counter:
+ switch m.Type {
+ case metrics.Int:
+ newMetric.Data = otelIntCounter(m)
+ default:
+ return nil
+ }
+ case metrics.Gauge:
+ switch m.Type {
+ case metrics.Int:
+ newMetric.Data = otelIntGauge(m)
+ case metrics.Float:
+ newMetric.Data = otelFloatGauge(m)
+ default:
+ return nil
+ }
+ case metrics.Timer:
+ switch m.Type {
+ case metrics.Float:
+ newMetric.Data = otelFloatGauge(m)
+ default:
+ return nil
+ }
+ case metrics.Histogram:
+ switch m.Type {
+ case metrics.Buckets:
+ newMetric.Data = otelHisto(m)
+ default:
+ return nil
+ }
+ default:
+ return nil
+ }
+ scopedOtelMetrics[m.Program] = append(scopedOtelMetrics[m.Program], newMetric)
+ return nil
+ })
+
+ if len(scopedOtelMetrics) == 0 {
+ return nil, nil
+ }
+
+ otelMetrics := make([]metricdata.ScopeMetrics, 0, len(scopedOtelMetrics))
+ for _, prog := range slices.Sorted(maps.Keys(scopedOtelMetrics)) {
+ otelMetrics = append(otelMetrics, metricdata.ScopeMetrics{Scope: instrumentation.Scope{Name: prog},
+ Metrics: scopedOtelMetrics[prog],
+ })
+ }
+ return otelMetrics, nil
+}
+
+func otelIntCounter(m *metrics.Metric) metricdata.Sum[int64] {
+ counter := metricdata.Sum[int64]{
+ DataPoints: make([]metricdata.DataPoint[int64], 0, len(m.LabelValues)),
+ Temporality: metricdata.CumulativeTemporality,
+ IsMonotonic: true,
+ }
+ lsc := make(chan *metrics.LabelSet)
+ go m.EmitLabelSets(lsc)
+ for ls := range lsc {
+ dp := metricdata.DataPoint[int64]{
+ Attributes: otelLabels(ls.Labels),
+ StartTime: processStartTime,
+ Time: ls.Datum.TimeUTC(),
+ Value: datum.GetInt(ls.Datum),
+ }
+ counter.DataPoints = append(counter.DataPoints, dp)
+ }
+ return counter
+}
+
+func otelIntGauge(m *metrics.Metric) metricdata.Gauge[int64] {
+ gauge := metricdata.Gauge[int64]{
+ DataPoints: make([]metricdata.DataPoint[int64], 0, len(m.LabelValues)),
+ }
+ lsc := make(chan *metrics.LabelSet)
+ go m.EmitLabelSets(lsc)
+ for ls := range lsc {
+ dp := metricdata.DataPoint[int64]{
+ Attributes: otelLabels(ls.Labels),
+ StartTime: processStartTime,
+ Time: ls.Datum.TimeUTC(),
+ Value: datum.GetInt(ls.Datum),
+ }
+ gauge.DataPoints = append(gauge.DataPoints, dp)
+ }
+ return gauge
+}
+
+func otelFloatGauge(m *metrics.Metric) metricdata.Gauge[float64] {
+ gauge := metricdata.Gauge[float64]{
+ DataPoints: make([]metricdata.DataPoint[float64], 0, len(m.LabelValues)),
+ }
+ lsc := make(chan *metrics.LabelSet)
+ go m.EmitLabelSets(lsc)
+ for ls := range lsc {
+ dp := metricdata.DataPoint[float64]{
+ Attributes: otelLabels(ls.Labels),
+ StartTime: processStartTime,
+ Time: ls.Datum.TimeUTC(),
+ Value: datum.GetFloat(ls.Datum),
+ }
+ gauge.DataPoints = append(gauge.DataPoints, dp)
+ }
+ return gauge
+}
+
+func otelHisto(m *metrics.Metric) metricdata.Histogram[float64] {
+ histo := metricdata.Histogram[float64]{
+ DataPoints: make([]metricdata.HistogramDataPoint[float64], 0, len(m.LabelValues)),
+ Temporality: metricdata.CumulativeTemporality,
+ }
+ lsc := make(chan *metrics.LabelSet)
+ go m.EmitLabelSets(lsc)
+ for ls := range lsc {
+ bounds, counts := otelConvertBuckets(datum.GetBuckets(ls.Datum))
+ dp := metricdata.HistogramDataPoint[float64]{
+ Attributes: otelLabels(ls.Labels),
+ StartTime: processStartTime,
+ Time: ls.Datum.TimeUTC(),
+ Count: datum.GetBucketsCount(ls.Datum),
+ Sum: datum.GetBucketsSum(ls.Datum),
+ Bounds: bounds,
+ BucketCounts: counts,
+ }
+ histo.DataPoints = append(histo.DataPoints, dp)
+ }
+ return histo
+}
+
+func otelConvertBuckets(d *datum.Buckets) (bounds []float64, counts []uint64) {
+ if len(d.Buckets) == 0 {
+ // Should never happen?
+ return nil, nil
+ }
+ // The last bucket may be the +Inf bucket, which is implied in OTel, but explicit in mtail.
+ if math.IsInf(d.Buckets[len(d.Buckets)-1].Range.Max, +1) {
+ bounds = make([]float64, len(d.Buckets)-1)
+ } else {
+ bounds = make([]float64, len(d.Buckets))
+ }
+ counts = make([]uint64, len(d.Buckets))
+ for i, bucket := range d.Buckets {
+ if bound := bucket.Range.Max; !math.IsInf(bound, +1) {
+ bounds[i] = bound
+ }
+ counts[i] = bucket.Count
+ }
+ return
+}
+
+func otelLabels(labels map[string]string) attribute.Set {
+ l := len(labels)
+ kvs := make([]attribute.KeyValue, l)
+ i := 0
+ for k, v := range labels {
+ kvs[i] = attribute.String(k, v)
+ i++
+ }
+ return attribute.NewSet(kvs...)
+}
+
+func (e *Exporter) InitOtel(ctx context.Context) error {
+ res, err := resource.New(ctx,
+ resource.WithHost(),
+ resource.WithAttributes(
+ attribute.String("service.name", "mtail"),
+ attribute.String("service.version", e.version),
+ ))
+ if err != nil {
+ return err
+ }
+ otlpexp, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithInsecure(), otlpmetricgrpc.WithTimeout(*writeDeadline))
+ if err != nil {
+ return err
+ }
+ reader := metric.NewPeriodicReader(otlpexp, metric.WithInterval(e.pushInterval), metric.WithProducer(e))
+ meterProvider := metric.NewMeterProvider(metric.WithReader(reader), metric.WithResource(res))
+ otel.SetMeterProvider(meterProvider)
+
+ e.wg.Add(1)
+ // Shut down the otel meter provider at exit
+ go func() {
+ defer e.wg.Done()
+ <-e.ctx.Done()
+ meterProvider.Shutdown(ctx)
+ }()
+
+ return nil
+}
diff --git a/internal/exporter/otel_test.go b/internal/exporter/otel_test.go
new file mode 100644
index 000000000..9c729b8a3
--- /dev/null
+++ b/internal/exporter/otel_test.go
@@ -0,0 +1,424 @@
+// Copyright 2025 The mtail Authors. All Rights Reserved.
+// This file is available under the Apache license.
+// SPDX-License-Identifier: Apache-2.0
+
+package exporter
+
+import (
+ "context"
+ "math"
+ "testing"
+ "time"
+
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/sdk/instrumentation"
+ "go.opentelemetry.io/otel/sdk/metric/metricdata"
+ "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
+)
+
+var otelTestCases = []struct {
+ name string
+ metrics []*metrics.Metric
+ expected []metricdata.ScopeMetrics
+}{
+ {
+ name: "empty",
+ metrics: []*metrics.Metric{},
+ },
+ {
+ name: "single",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at ",
+ Data: metricdata.Sum[int64]{
+ Temporality: metricdata.CumulativeTemporality,
+ IsMonotonic: true,
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "dimensioned",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Counter,
+ Keys: []string{"a", "b"},
+ LabelValues: []*metrics.LabelValue{{Labels: []string{"1", "2"}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at ",
+ Data: metricdata.Sum[int64]{
+ Temporality: metricdata.CumulativeTemporality,
+ IsMonotonic: true,
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Attributes: attribute.NewSet(attribute.String("a", "1"), attribute.String("b", "2")),
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "gauge",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Gauge,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at ",
+ Data: metricdata.Gauge[int64]{
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "float gauge",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Gauge,
+ Type: metrics.Float,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeFloat(1.0, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at ",
+ Data: metricdata.Gauge[float64]{
+ DataPoints: []metricdata.DataPoint[float64]{
+ {
+ Value: 1.0,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "timer",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Timer,
+ Type: metrics.Float,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeFloat(1, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at ",
+ Data: metricdata.Gauge[float64]{
+ DataPoints: []metricdata.DataPoint[float64]{
+ {
+ Value: 1.0,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "text",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Text,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeString("hi", time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{},
+ },
+ {
+ name: "quotes",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Counter,
+ Keys: []string{"a"},
+ LabelValues: []*metrics.LabelValue{{Labels: []string{"str\"bang\"blah"}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at ",
+ Data: metricdata.Sum[int64]{
+ Temporality: metricdata.CumulativeTemporality,
+ IsMonotonic: true,
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Attributes: attribute.NewSet(attribute.String("a", "str\"bang\"blah")),
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "description",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Counter,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ Source: "location.mtail:37",
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at location.mtail:37",
+ Data: metricdata.Sum[int64]{
+ Temporality: metricdata.CumulativeTemporality,
+ IsMonotonic: true,
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "histo",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Histogram,
+ Type: metrics.Buckets,
+ Keys: []string{"a"},
+ LabelValues: []*metrics.LabelValue{{Labels: []string{"bar"}, Value: datum.MakeBuckets([]datum.Range{{Min: 0, Max: 1}, {Min: 1, Max: 2}}, time.Unix(0, 0))}},
+ Source: "location.mtail:37",
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at location.mtail:37",
+ Data: metricdata.Histogram[float64]{
+ Temporality: metricdata.CumulativeTemporality,
+ DataPoints: []metricdata.HistogramDataPoint[float64]{
+ {
+ Count: 0,
+ Sum: 0,
+ Bounds: []float64{1, 2},
+ BucketCounts: []uint64{0, 0, 0},
+ Attributes: attribute.NewSet(attribute.String("a", "bar")),
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "histo-count-eq-inf",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo",
+ Program: "test",
+ Kind: metrics.Histogram,
+ Type: metrics.Buckets,
+ Keys: []string{"a"},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Labels: []string{"bar"},
+ Value: &datum.Buckets{
+ Buckets: []datum.BucketCount{
+ {
+ Range: datum.Range{Min: 0, Max: 1},
+ Count: 1,
+ },
+ {
+ Range: datum.Range{Min: 1, Max: 2},
+ Count: 1,
+ },
+ {
+ Range: datum.Range{Min: 2, Max: math.Inf(+1)},
+ Count: 2,
+ },
+ },
+ Count: 4,
+ Sum: 5,
+ },
+ },
+ },
+ Source: "location.mtail:37",
+ },
+ },
+ expected: []metricdata.ScopeMetrics{{
+ Scope: instrumentation.Scope{Name: "test"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo",
+ Description: "foo defined at location.mtail:37",
+ Data: metricdata.Histogram[float64]{
+ Temporality: metricdata.CumulativeTemporality,
+ DataPoints: []metricdata.HistogramDataPoint[float64]{
+ {
+ Count: 4,
+ Sum: 5,
+ Bounds: []float64{1, 2},
+ BucketCounts: []uint64{1, 1, 2},
+ Attributes: attribute.NewSet(attribute.String("a", "bar")),
+ },
+ },
+ },
+ },
+ },
+ }},
+ },
+ {
+ name: "two scopes",
+ metrics: []*metrics.Metric{
+ {
+ Name: "foo1",
+ Program: "test1",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ },
+ {
+ Name: "foo2",
+ Program: "test2",
+ Kind: metrics.Gauge,
+ Type: metrics.Int,
+ LabelValues: []*metrics.LabelValue{{Labels: []string{}, Value: datum.MakeInt(1, time.Unix(0, 0))}},
+ },
+ },
+ expected: []metricdata.ScopeMetrics{
+ {
+ Scope: instrumentation.Scope{Name: "test1"},
+ Metrics: []metricdata.Metrics{
+ {
+ Name: "foo1",
+ Description: "foo1 defined at ",
+ Data: metricdata.Sum[int64]{
+ Temporality: metricdata.CumulativeTemporality,
+ IsMonotonic: true,
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ Scope: instrumentation.Scope{Name: "test2"},
+ Metrics: []metricdata.Metrics{{
+ Name: "foo2",
+ Description: "foo2 defined at ",
+ Data: metricdata.Gauge[int64]{
+ DataPoints: []metricdata.DataPoint[int64]{
+ {
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+}
+
+func TestOtelExport(t *testing.T) {
+ for _, tc := range otelTestCases {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ ms := metrics.NewStore()
+ for _, metric := range tc.metrics {
+ testutil.FatalIfErr(t, ms.Add(metric))
+ }
+ opts := []Option{
+ Hostname("gunstar"),
+ }
+ e, err := New(ctx, ms, opts...)
+ testutil.FatalIfErr(t, err)
+ output, err := e.Produce(ctx)
+ if err != nil {
+ t.Error(err)
+ }
+ if len(output) != len(tc.expected) {
+ t.Fatalf("output size doesn't match expected want %d got %d", len(tc.expected), len(output))
+ }
+ for i := range tc.expected {
+ metricdatatest.AssertEqual(t, tc.expected[i], output[i], metricdatatest.IgnoreTimestamp())
+ }
+ e.Stop()
+ })
+ }
+}
diff --git a/internal/exporter/prometheus.go b/internal/exporter/prometheus.go
index 3d8f04616..bf6a61527 100644
--- a/internal/exporter/prometheus.go
+++ b/internal/exporter/prometheus.go
@@ -10,8 +10,8 @@ import (
"strings"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/expfmt"
)
@@ -34,6 +34,9 @@ func (e *Exporter) Collect(c chan<- prometheus.Metric) {
/* #nosec G104 always retursn nil */
e.store.Range(func(m *metrics.Metric) error {
+ if m.Hidden {
+ return nil
+ }
m.RLock()
// We don't have a way of converting text metrics to prometheus format.
if m.Kind == metrics.Text {
diff --git a/internal/exporter/prometheus_test.go b/internal/exporter/prometheus_test.go
index e86f14d3b..3d11bcc14 100644
--- a/internal/exporter/prometheus_test.go
+++ b/internal/exporter/prometheus_test.go
@@ -6,14 +6,16 @@ package exporter
import (
"bytes"
"context"
+ "fmt"
"math"
+ "strconv"
"strings"
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
promtest "github.com/prometheus/client_golang/prometheus/testutil"
)
@@ -191,7 +193,7 @@ foo{prog="test1"} 1
Program: "test",
Kind: metrics.Histogram,
Keys: []string{"a"},
- LabelValues: []*metrics.LabelValue{{Labels: []string{"bar"}, Value: datum.MakeBuckets([]datum.Range{{0, 1}, {1, 2}}, time.Unix(0, 0))}},
+ LabelValues: []*metrics.LabelValue{{Labels: []string{"bar"}, Value: datum.MakeBuckets([]datum.Range{{Min: 0, Max: 1}, {Min: 1, Max: 2}}, time.Unix(0, 0))}},
Source: "location.mtail:37",
},
},
@@ -356,3 +358,138 @@ func TestWritePrometheus(t *testing.T) {
})
}
}
+
+func BenchmarkWritePrometheus(b *testing.B) {
+ for _, n := range []int{100, 1000, 10000} {
+ b.Run(fmt.Sprintf("labelvalues=%d", n), func(b *testing.B) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ ms := metrics.NewStore()
+ m := metrics.NewMetric("test_metric", "test", metrics.Counter, metrics.Int, "id")
+ for i := 0; i < n; i++ {
+ d, err := m.GetDatum(strconv.Itoa(i))
+ if err != nil {
+ b.Fatal(err)
+ }
+ datum.SetInt(d, int64(i), time.Now())
+ }
+ if err := ms.Add(m); err != nil {
+ b.Fatal(err)
+ }
+
+ opts := []Option{Hostname("gunstar"), OmitProgLabel()}
+ e, err := New(ctx, ms, opts...)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var buf bytes.Buffer
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ if err := e.Write(&buf); err != nil {
+ b.Fatal(err)
+ }
+ }
+ e.Stop()
+ })
+ }
+ for _, n := range []int{100, 1000, 10000} {
+ b.Run(fmt.Sprintf("metrics=%d", n), func(b *testing.B) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ ms := metrics.NewStore()
+ for i := 0; i < n; i++ {
+ m := metrics.NewMetric(fmt.Sprintf("metric_%d", i), "test", metrics.Counter, metrics.Int)
+ d, err := m.GetDatum()
+ if err != nil {
+ b.Fatal(err)
+ }
+ datum.SetInt(d, int64(i), time.Now())
+ if err := ms.Add(m); err != nil {
+ b.Fatal(err)
+ }
+ }
+
+ opts := []Option{Hostname("gunstar"), OmitProgLabel()}
+ e, err := New(ctx, ms, opts...)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var buf bytes.Buffer
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ if err := e.Write(&buf); err != nil {
+ b.Fatal(err)
+ }
+ }
+ e.Stop()
+ })
+ }
+}
+
+func TestWritePrometheusManyLabelValues(t *testing.T) {
+ counts := []int{100, 1000, 10000}
+ if testing.Short() {
+ counts = []int{100}
+ }
+ for _, n := range counts {
+ t.Run(fmt.Sprintf("count=%d", n), func(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ ms := metrics.NewStore()
+ m := metrics.NewMetric("test_metric", "test", metrics.Counter, metrics.Int, "id")
+ for i := 0; i < n; i++ {
+ d, err := m.GetDatum(strconv.Itoa(i))
+ testutil.FatalIfErr(t, err)
+ datum.SetInt(d, int64(i), time.Now())
+ }
+ testutil.FatalIfErr(t, ms.Add(m))
+
+ opts := []Option{Hostname("gunstar"), OmitProgLabel()}
+ e, err := New(ctx, ms, opts...)
+ testutil.FatalIfErr(t, err)
+
+ var buf bytes.Buffer
+ err = e.Write(&buf)
+ testutil.FatalIfErr(t, err)
+ t.Logf("Wrote %d bytes for %d label values", buf.Len(), n)
+ e.Stop()
+ })
+ }
+}
+
+func TestWritePrometheusManyMetrics(t *testing.T) {
+ counts := []int{100, 1000, 10000}
+ if testing.Short() {
+ counts = []int{100}
+ }
+ for _, n := range counts {
+ t.Run(fmt.Sprintf("count=%d", n), func(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ ms := metrics.NewStore()
+ for i := 0; i < n; i++ {
+ m := metrics.NewMetric(fmt.Sprintf("metric_%d", i), "test", metrics.Counter, metrics.Int)
+ d, err := m.GetDatum()
+ testutil.FatalIfErr(t, err)
+ datum.SetInt(d, int64(i), time.Now())
+ testutil.FatalIfErr(t, ms.Add(m))
+ }
+
+ opts := []Option{Hostname("gunstar"), OmitProgLabel()}
+ e, err := New(ctx, ms, opts...)
+ testutil.FatalIfErr(t, err)
+
+ var buf bytes.Buffer
+ err = e.Write(&buf)
+ testutil.FatalIfErr(t, err)
+ t.Logf("Wrote %d bytes for %d metrics", buf.Len(), n)
+ e.Stop()
+ })
+ }
+}
diff --git a/internal/exporter/statsd.go b/internal/exporter/statsd.go
index 8cbcca404..6fb308451 100644
--- a/internal/exporter/statsd.go
+++ b/internal/exporter/statsd.go
@@ -9,7 +9,7 @@ import (
"fmt"
"time"
- "github.com/google/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics"
)
var (
diff --git a/internal/exporter/varz.go b/internal/exporter/varz.go
index e8c400b27..44fdeb418 100644
--- a/internal/exporter/varz.go
+++ b/internal/exporter/varz.go
@@ -10,7 +10,7 @@ import (
"sort"
"strings"
- "github.com/google/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics"
)
var exportVarzTotal = expvar.NewInt("exporter_varz_total")
@@ -27,6 +27,9 @@ func (e *Exporter) HandleVarz(w http.ResponseWriter, r *http.Request) {
return r.Context().Err()
default:
}
+ if m.Hidden {
+ return nil
+ }
m.RLock()
exportVarzTotal.Add(1)
lc := make(chan *metrics.LabelSet)
diff --git a/internal/exporter/varz_test.go b/internal/exporter/varz_test.go
index 9026be7be..ff7a94f51 100644
--- a/internal/exporter/varz_test.go
+++ b/internal/exporter/varz_test.go
@@ -11,9 +11,9 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var handleVarzTests = []struct {
diff --git a/internal/logline/BUILD.bazel b/internal/logline/BUILD.bazel
new file mode 100644
index 000000000..5776c3b92
--- /dev/null
+++ b/internal/logline/BUILD.bazel
@@ -0,0 +1,8 @@
+load("@rules_go//go:def.bzl", "go_library")
+
+go_library(
+ name = "logline",
+ srcs = ["logline.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/logline",
+ visibility = ["//:__subpackages__"],
+)
diff --git a/internal/logline/logline.go b/internal/logline/logline.go
index 996e39e5a..817cfe4e7 100644
--- a/internal/logline/logline.go
+++ b/internal/logline/logline.go
@@ -3,17 +3,28 @@
package logline
-import "context"
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/binary"
+)
// LogLine contains all the information about a line just read from a log.
type LogLine struct {
Context context.Context
- Filename string // The log filename that this line was read from
- Line string // The text of the log line itself up to the newline.
+ Filename string // The log filename that this line was read from
+ Filenamehash uint32 // stored for efficient key lookup
+ Line string // The text of the log line itself up to the newline.
}
// New creates a new LogLine object.
-func New(ctx context.Context, filename string, line string) *LogLine {
- return &LogLine{ctx, filename, line}
+func New(ctx context.Context, filename string, filenamehash uint32, line string) *LogLine {
+ return &LogLine{ctx, filename, filenamehash, line}
+}
+
+// External as unit tests need it
+func GetHash(filename string) uint32 {
+ hash := sha256.Sum256([]byte(filename))
+ return binary.BigEndian.Uint32(hash[:8])
}
diff --git a/internal/metrics/BUILD.bazel b/internal/metrics/BUILD.bazel
new file mode 100644
index 000000000..cdefcbd35
--- /dev/null
+++ b/internal/metrics/BUILD.bazel
@@ -0,0 +1,35 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "metrics",
+ srcs = [
+ "metric.go",
+ "store.go",
+ "testing.go",
+ "type.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/metrics",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics/datum",
+ "@com_github_golang_glog//:glog",
+ "@com_github_pkg_errors//:errors",
+ ],
+)
+
+go_test(
+ name = "metrics_test",
+ size = "small",
+ srcs = [
+ "metric_test.go",
+ "store_bench_test.go",
+ "store_test.go",
+ ],
+ embed = [":metrics"],
+ tags = ["benchmark"],
+ deps = [
+ "//internal/metrics/datum",
+ "//internal/testutil",
+ "@com_github_golang_glog//:glog",
+ ],
+)
diff --git a/internal/metrics/datum/BUILD.bazel b/internal/metrics/datum/BUILD.bazel
new file mode 100644
index 000000000..5e15ccc1c
--- /dev/null
+++ b/internal/metrics/datum/BUILD.bazel
@@ -0,0 +1,27 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "datum",
+ srcs = [
+ "buckets.go",
+ "datum.go",
+ "float.go",
+ "int.go",
+ "string.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/metrics/datum",
+ visibility = ["//:__subpackages__"],
+)
+
+go_test(
+ name = "datum_test",
+ size = "small",
+ srcs = [
+ "buckets_test.go",
+ "datum_test.go",
+ "int_test.go",
+ ],
+ embed = [":datum"],
+ tags = ["benchmark"],
+ deps = ["//internal/testutil"],
+)
diff --git a/internal/metrics/datum/buckets.go b/internal/metrics/datum/buckets.go
index ef15f0cb0..b1f3b8625 100644
--- a/internal/metrics/datum/buckets.go
+++ b/internal/metrics/datum/buckets.go
@@ -39,6 +39,7 @@ func (d *Buckets) ValueString() string {
return fmt.Sprintf("%g", d.GetSum())
}
+// Observe records a value in the buckets. The buckets contain the number of samples between (min,max]
func (d *Buckets) Observe(v float64, ts time.Time) {
d.Lock()
defer d.Unlock()
diff --git a/internal/metrics/datum/buckets_test.go b/internal/metrics/datum/buckets_test.go
index d0a54df7f..c2f03ad84 100644
--- a/internal/metrics/datum/buckets_test.go
+++ b/internal/metrics/datum/buckets_test.go
@@ -9,13 +9,14 @@ import (
"testing/quick"
"time"
- "github.com/google/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
-func TestBucketContains(t *testing.T) {
- if err := quick.Check(func(min, max, val float64) bool {
- r := &datum.Range{Min: min, Max: max}
- truth := val < max && val >= min
+func TestRangeContains(t *testing.T) {
+ if err := quick.Check(func(lo, hi, val float64) bool {
+ r := &datum.Range{Min: lo, Max: hi}
+ truth := val < hi && val >= lo
return truth == r.Contains(val)
}, nil); err != nil {
t.Error(err)
@@ -38,10 +39,11 @@ func TestMakeBucket(t *testing.T) {
t.Errorf("count not 1, got %v", r)
}
bs := datum.GetBucketsCumByMax(b)
- if r := datum.GetBucketsCount(b); r != bs[math.Inf(+1)] {
- t.Errorf("Inf bucket des not equal total observation count: %v vs %v", bs[math.Inf(+1)], r)
- }
- if len(bs) != len(r)+1 {
- t.Errorf("missing buckets from BucketsByMax: expected %d, got %v", len(r)+1, len(bs))
+ expected := map[float64]uint64{
+ 1: 0,
+ 2: 1,
+ 4: 1,
+ math.Inf(+1): 1,
}
+ testutil.ExpectNoDiff(t, expected, bs)
}
diff --git a/internal/metrics/datum/datum_test.go b/internal/metrics/datum/datum_test.go
index a9d36db65..aeaf79c26 100644
--- a/internal/metrics/datum/datum_test.go
+++ b/internal/metrics/datum/datum_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestDatumSetAndValue(t *testing.T) {
diff --git a/internal/metrics/metric.go b/internal/metrics/metric.go
index bf8ec95d5..d0fb54ba7 100644
--- a/internal/metrics/metric.go
+++ b/internal/metrics/metric.go
@@ -15,7 +15,7 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
"github.com/pkg/errors"
)
diff --git a/internal/metrics/metric_test.go b/internal/metrics/metric_test.go
index 3440808e3..279c5381a 100644
--- a/internal/metrics/metric_test.go
+++ b/internal/metrics/metric_test.go
@@ -13,8 +13,8 @@ import (
"testing/quick"
"time"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestKindType(t *testing.T) {
diff --git a/internal/metrics/store.go b/internal/metrics/store.go
index d82bb43f1..0da47c772 100644
--- a/internal/metrics/store.go
+++ b/internal/metrics/store.go
@@ -53,9 +53,6 @@ func (s *Store) Add(m *Metric) error {
if v.Type != m.Type {
continue
}
- if v.Source != m.Source {
- continue
- }
dupeIndex = i
glog.V(2).Infof("v keys: %v m.keys: %v", v.Keys, m.Keys)
// If a set of label keys has changed, discard
diff --git a/internal/metrics/store_test.go b/internal/metrics/store_test.go
index 096fe07f6..2d6d29621 100644
--- a/internal/metrics/store_test.go
+++ b/internal/metrics/store_test.go
@@ -9,10 +9,37 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
+func TestLimitWithHidden(t *testing.T) {
+ s := NewStore()
+ m := NewMetric("hidden_metric", "prog", Counter, Int, "foo")
+ m.Hidden = true
+ m.Limit = 1
+ testutil.FatalIfErr(t, s.Add(m))
+
+ _, err := m.GetDatum("a")
+ testutil.FatalIfErr(t, err)
+ testutil.FatalIfErr(t, s.Gc())
+
+ _, err = m.GetDatum("b")
+ testutil.FatalIfErr(t, err)
+ testutil.FatalIfErr(t, s.Gc())
+
+ _, err = m.GetDatum("c")
+ testutil.FatalIfErr(t, err)
+ testutil.FatalIfErr(t, s.Gc())
+
+ if len(m.LabelValues) > 2 {
+ t.Errorf("Expected 2 labelvalues got %#v", m.LabelValues)
+ }
+ if x := m.FindLabelValueOrNil([]string{"a"}); x != nil {
+ t.Errorf("found label a which is unexpected: %#v", x)
+ }
+}
+
func TestMatchingKind(t *testing.T) {
s := NewStore()
m1 := NewMetric("foo", "prog", Counter, Int)
@@ -63,9 +90,30 @@ func TestDuplicateMetric(t *testing.T) {
}
}
+func TestDuplicateMetricWithDifferentSource(t *testing.T) {
+ // Simulates SIGHUP reload where the same metric from the same program
+ // has a different source location (line number changed due to file edit).
+ // Should still be treated as a duplicate and replaced, not appended.
+ s := NewStore()
+ m1 := NewMetric("foo", "prog", Counter, Int)
+ m1.SetSource("test.mtail:5:1")
+ testutil.FatalIfErr(t, s.Add(m1))
+
+ m2 := NewMetric("foo", "prog", Counter, Int)
+ m2.SetSource("test.mtail:11:1")
+ testutil.FatalIfErr(t, s.Add(m2))
+
+ if len(s.Metrics["foo"]) != 1 {
+ t.Fatalf("expected 1 metric after reload with changed source, got %d: %v", len(s.Metrics["foo"]), s.Metrics["foo"])
+ }
+ if s.Metrics["foo"][0].Source != "test.mtail:11:1" {
+ t.Fatalf("expected metric source to be updated to new source, got %q", s.Metrics["foo"][0].Source)
+ }
+}
+
// A program can add a metric with the same name and of different type.
// Prometheus behavior in this case is undefined. @see
-// https://github.com/google/mtail/issues/130
+// https://github.com/jaqx0r/mtail/issues/130
func TestAddMetricDifferentType(t *testing.T) {
expected := 2
s := NewStore()
diff --git a/internal/mtail/BUILD.bazel b/internal/mtail/BUILD.bazel
new file mode 100644
index 000000000..0ed47b239
--- /dev/null
+++ b/internal/mtail/BUILD.bazel
@@ -0,0 +1,111 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "mtail",
+ srcs = [
+ "buildinfo.go",
+ "httpstatus.go",
+ "mtail.go",
+ "options.go",
+ "testing.go",
+ ],
+ embedsrcs = ["logo.ico"],
+ importpath = "github.com/jaqx0r/mtail/internal/mtail",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/exporter",
+ "//internal/logline",
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/runtime",
+ "//internal/tailer",
+ "//internal/testutil",
+ "//internal/waker",
+ "@com_github_golang_glog//:glog",
+ "@com_github_prometheus_client_golang//prometheus",
+ "@com_github_prometheus_client_golang//prometheus/collectors",
+ "@com_github_prometheus_client_golang//prometheus/collectors/version",
+ "@com_github_prometheus_client_golang//prometheus/promhttp",
+ "@com_github_prometheus_common//version",
+ "@io_opencensus_go//trace",
+ "@io_opencensus_go//zpages",
+ "@io_opencensus_go_contrib_exporter_jaeger//:jaeger",
+ ],
+)
+
+go_test(
+ name = "mtail_test",
+ size = "small",
+ srcs = [
+ "basic_tail_integration_test.go",
+ "compile_only_integration_test.go",
+ "examples_integration_test.go",
+ "examples_integration_unix_test.go",
+ "exec_integration_test.go",
+ "log_deletion_integration_unix_test.go",
+ "log_filter_integration_test.go",
+ "log_glob_integration_test.go",
+ "log_rotation_integration_test.go",
+ "log_rotation_integration_unix_test.go",
+ "log_truncation_integration_test.go",
+ "mtail_test.go",
+ "multiple_levels_directory_integration_test.go",
+ "multiple_lines_integration_test.go",
+ "partial_line_integration_test.go",
+ "permission_denied_integration_unix_test.go",
+ "prog_load_integration_test.go",
+ "read_pipe_integration_unix_test.go",
+ "relative_path_pattern_integration_test.go",
+ "unix_socket_export_integration_test.go",
+ ],
+ data = glob(["testdata/**"]) + [
+ "//cmd/mtail",
+ "//examples",
+ ],
+ embed = [":mtail"],
+ tags = ["benchmark"],
+ deps = [
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/mtail/golden",
+ "//internal/testutil",
+ "//internal/waker",
+ "@com_github_golang_glog//:glog",
+ "@rules_go//go/tools/bazel",
+ ] + select({
+ "@rules_go//go/platform:aix": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:android": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:darwin": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:dragonfly": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:freebsd": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:illumos": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:ios": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:linux": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:netbsd": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:openbsd": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:solaris": [
+ "@org_golang_x_sys//unix",
+ ],
+ "//conditions:default": [],
+ }),
+)
diff --git a/internal/mtail/basic_tail_integration_test.go b/internal/mtail/basic_tail_integration_test.go
index 1bfc95f9f..017a49e6e 100644
--- a/internal/mtail/basic_tail_integration_test.go
+++ b/internal/mtail/basic_tail_integration_test.go
@@ -10,8 +10,8 @@ import (
"sync"
"testing"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestBasicTail(t *testing.T) {
diff --git a/internal/mtail/buildinfo.go b/internal/mtail/buildinfo.go
index eb5e9f1dd..ad618f70f 100644
--- a/internal/mtail/buildinfo.go
+++ b/internal/mtail/buildinfo.go
@@ -13,9 +13,14 @@ type BuildInfo struct {
Branch string
Version string
Revision string
+ EmbedLabel string
}
func (b BuildInfo) String() string {
+ label := ""
+ if b.EmbedLabel != "" {
+ label = fmt.Sprintf(" label %s", b.EmbedLabel)
+ }
return fmt.Sprintf(
"mtail version %s git revision %s go version %s go arch %s go os %s",
b.Version,
@@ -23,5 +28,5 @@ func (b BuildInfo) String() string {
runtime.Version(),
runtime.GOARCH,
runtime.GOOS,
- )
+ ) + label
}
diff --git a/internal/mtail/compile_only_integration_test.go b/internal/mtail/compile_only_integration_test.go
index af6fa5163..8a0e4fdde 100644
--- a/internal/mtail/compile_only_integration_test.go
+++ b/internal/mtail/compile_only_integration_test.go
@@ -10,9 +10,9 @@ import (
"strings"
"testing"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestBadProgramFailsCompilation(t *testing.T) {
diff --git a/internal/mtail/examples_integration_test.go b/internal/mtail/examples_integration_test.go
index 3dca5fd94..1f63a93d6 100644
--- a/internal/mtail/examples_integration_test.go
+++ b/internal/mtail/examples_integration_test.go
@@ -13,12 +13,12 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/mtail/golden"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/mtail/golden"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
const exampleTimeout = 10 * time.Second
@@ -116,6 +116,9 @@ func TestExamplePrograms(t *testing.T) {
var storeList metrics.MetricSlice
store.Range(func(m *metrics.Metric) error {
+ if m.Hidden {
+ return nil
+ }
storeList = append(storeList, m)
return nil
})
diff --git a/internal/mtail/examples_integration_unix_test.go b/internal/mtail/examples_integration_unix_test.go
index bc93e91e0..e9ca2ebca 100644
--- a/internal/mtail/examples_integration_unix_test.go
+++ b/internal/mtail/examples_integration_unix_test.go
@@ -18,11 +18,11 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
"golang.org/x/sys/unix"
)
diff --git a/internal/mtail/exec_integration_test.go b/internal/mtail/exec_integration_test.go
index ba87bade9..e81e65731 100644
--- a/internal/mtail/exec_integration_test.go
+++ b/internal/mtail/exec_integration_test.go
@@ -5,37 +5,21 @@ package mtail_test
import (
"context"
- "errors"
"fmt"
"os/exec"
- "path/filepath"
"syscall"
"testing"
"time"
- "github.com/golang/glog"
- "github.com/google/mtail/internal/testutil"
+ "github.com/bazelbuild/rules_go/go/tools/bazel"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
-var mtailPath string
-
-func init() {
- path, err := exec.LookPath(filepath.Join("..", "..", "mtail"))
- if errors.Is(err, exec.ErrDot) {
- err = nil
- }
- if err != nil {
- glog.Infof("exec_integration_test init(): %v", err)
- }
- mtailPath = path
-}
-
func TestExecMtail(t *testing.T) {
- if mtailPath == "" {
- t.Log("mtail binary not found, skipping")
- t.Skip()
+ mtailPath, ok := bazel.FindBinary("cmd/mtail", "mtail")
+ if !ok {
+ t.Fatal("`mtail` not found in runfiles")
}
-
cs := []string{
"-progs",
"../../examples",
diff --git a/internal/mtail/golden/BUILD.bazel b/internal/mtail/golden/BUILD.bazel
new file mode 100644
index 000000000..2ba65dc26
--- /dev/null
+++ b/internal/mtail/golden/BUILD.bazel
@@ -0,0 +1,26 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "golden",
+ srcs = ["reader.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/mtail/golden",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "golden_test",
+ size = "small",
+ srcs = ["reader_test.go"],
+ data = ["reader_test.golden"],
+ embed = [":golden"],
+ deps = [
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/testutil",
+ ],
+)
diff --git a/internal/mtail/golden/reader.go b/internal/mtail/golden/reader.go
index be3e12ce2..deb72618e 100644
--- a/internal/mtail/golden/reader.go
+++ b/internal/mtail/golden/reader.go
@@ -13,8 +13,8 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
)
var varRe = regexp.MustCompile(`^(counter|gauge|timer|text|histogram) ([^ ]+)(?: {([^}]+)})?(?: (\S+))?(?: (.+))?`)
diff --git a/internal/mtail/golden/reader_test.go b/internal/mtail/golden/reader_test.go
index 2d8e577b9..6cc4767c5 100644
--- a/internal/mtail/golden/reader_test.go
+++ b/internal/mtail/golden/reader_test.go
@@ -6,9 +6,9 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var expectedMetrics = metrics.MetricSlice{
diff --git a/internal/mtail/httpstatus.go b/internal/mtail/httpstatus.go
index 2db5cc51f..c9922e280 100644
--- a/internal/mtail/httpstatus.go
+++ b/internal/mtail/httpstatus.go
@@ -4,6 +4,7 @@
package mtail
import (
+ _ "embed"
"html/template"
"net/http"
@@ -76,6 +77,9 @@ func (m *Server) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
}
}
+//go:embed logo.ico
+var logoFavicon []byte
+
// FaviconHandler is used to serve up the favicon.ico for mtail's http server.
func FaviconHandler(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "image/x-icon")
diff --git a/internal/mtail/log_deletion_integration_unix_test.go b/internal/mtail/log_deletion_integration_unix_test.go
index fa1b87f9e..bd37f0c66 100644
--- a/internal/mtail/log_deletion_integration_unix_test.go
+++ b/internal/mtail/log_deletion_integration_unix_test.go
@@ -11,8 +11,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
// TestLogDeletion is a unix-only test because on Windows files with open read handles cannot be deleted.
diff --git a/internal/mtail/log_filter_integration_test.go b/internal/mtail/log_filter_integration_test.go
new file mode 100644
index 000000000..1ea5d8251
--- /dev/null
+++ b/internal/mtail/log_filter_integration_test.go
@@ -0,0 +1,120 @@
+// Copyright 2025 The mtail Authors. All Rights Reserved.
+// This file is available under the Apache license.
+
+package mtail_test
+
+import (
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+ "strings"
+ "sync"
+ "testing"
+
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
+)
+
+func TestIncludeLog(t *testing.T) {
+ testutil.SkipIfShort(t)
+
+ logDir := testutil.TestTempDir(t)
+
+ // The logfile isn't known until now so we need to create out own Program Dir, copy in the program and update the log_filter
+ progDir := testutil.TestTempDir(t)
+
+ content, err := ioutil.ReadFile("../../examples/log_filter.mtail")
+ testutil.FatalIfErr(t, err)
+
+ logFile := filepath.Join(logDir, "log")
+
+ updatedContent := strings.ReplaceAll(string(content), "<>", logFile)
+
+ progFile := filepath.Join(progDir, "/test.mtail")
+
+ // Write the updated content to the destination file
+ err = ioutil.WriteFile(progFile, []byte(updatedContent), 0644)
+
+ testutil.FatalIfErr(t, err)
+
+ // Verify the file was written correctly
+ writtenContent, err := ioutil.ReadFile(progFile)
+ testutil.FatalIfErr(t, err)
+ if string(writtenContent) != updatedContent {
+ t.Fatalf("File content mismatch: expected %q, got %q", updatedContent, string(writtenContent))
+ }
+
+ m, stopM := mtail.TestStartServer(t, 1, 1, mtail.LogPathPatterns(logFile), mtail.ProgramPath(progFile))
+ defer stopM()
+
+ lineCountCheck := m.ExpectMapExpvarDeltaWithDeadline("log_lines_total", logFile, 3)
+ progLineCountCheck := m.ExpectMapExpvarDeltaWithDeadline("prog_lines_total", "test.mtail", 3)
+ logCountCheck := m.ExpectExpvarDeltaWithDeadline("log_count", 1)
+
+ f := testutil.TestOpenFile(t, logFile)
+ defer f.Close()
+ m.AwakenPatternPollers(1, 1) // Find `logFile`
+ m.AwakenLogStreams(1, 1) // Force a sync to EOF
+
+ for i := 1; i <= 3; i++ {
+ testutil.WriteString(t, f, fmt.Sprintf("%d\n", i))
+ }
+ m.AwakenLogStreams(1, 1) // Expect to read 3 lines here.
+
+ var wg sync.WaitGroup
+ wg.Add(3)
+ go func() {
+ defer wg.Done()
+ lineCountCheck()
+ }()
+ go func() {
+ defer wg.Done()
+ logCountCheck()
+ }()
+ go func() {
+ defer wg.Done()
+ progLineCountCheck()
+ }()
+ wg.Wait()
+}
+
+func TestExcludeLog(t *testing.T) {
+ testutil.SkipIfShort(t)
+
+ logDir := testutil.TestTempDir(t)
+
+ logFile := filepath.Join(logDir, "log")
+
+ m, stopM := mtail.TestStartServer(t, 1, 1, mtail.LogPathPatterns(logFile), mtail.ProgramPath(mtail.ProgramPath("../../examples/log_filter_ignore.mtail")))
+ defer stopM()
+
+ lineCountCheck := m.ExpectMapExpvarDeltaWithDeadline("log_lines_total", logFile, 3)
+ progLineCountCheck := m.ExpectMapExpvarDeltaWithDeadline("prog_lines_total", "log_filter_ignore.mtail", 0) // not read
+ logCountCheck := m.ExpectExpvarDeltaWithDeadline("log_count", 1)
+
+ f := testutil.TestOpenFile(t, logFile)
+ defer f.Close()
+ m.AwakenPatternPollers(1, 1) // Find `logFile`
+ m.AwakenLogStreams(1, 1) // Force a sync to EOF
+
+ for i := 1; i <= 3; i++ {
+ testutil.WriteString(t, f, fmt.Sprintf("%d\n", i))
+ }
+ m.AwakenLogStreams(1, 1) // Expect to read 3 lines here.
+
+ var wg sync.WaitGroup
+ wg.Add(3)
+ go func() {
+ defer wg.Done()
+ lineCountCheck()
+ }()
+ go func() {
+ defer wg.Done()
+ logCountCheck()
+ }()
+ go func() {
+ defer wg.Done()
+ progLineCountCheck()
+ }()
+ wg.Wait()
+}
diff --git a/internal/mtail/log_glob_integration_test.go b/internal/mtail/log_glob_integration_test.go
index 9e3770c23..7587abc36 100644
--- a/internal/mtail/log_glob_integration_test.go
+++ b/internal/mtail/log_glob_integration_test.go
@@ -10,8 +10,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestGlobBeforeStart(t *testing.T) {
diff --git a/internal/mtail/log_rotation_integration_test.go b/internal/mtail/log_rotation_integration_test.go
index bf2ed33e4..4b4390fca 100644
--- a/internal/mtail/log_rotation_integration_test.go
+++ b/internal/mtail/log_rotation_integration_test.go
@@ -11,8 +11,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestLogRotationBySoftLinkChange(t *testing.T) {
diff --git a/internal/mtail/log_rotation_integration_unix_test.go b/internal/mtail/log_rotation_integration_unix_test.go
index ef310e93b..1f2228b3d 100644
--- a/internal/mtail/log_rotation_integration_unix_test.go
+++ b/internal/mtail/log_rotation_integration_unix_test.go
@@ -13,8 +13,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
// TestLogRotationByRename is a unix-specific test because on Windows, files
diff --git a/internal/mtail/log_truncation_integration_test.go b/internal/mtail/log_truncation_integration_test.go
index 3665e99ec..a3831d13c 100644
--- a/internal/mtail/log_truncation_integration_test.go
+++ b/internal/mtail/log_truncation_integration_test.go
@@ -9,8 +9,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestLogTruncation(t *testing.T) {
diff --git a/internal/mtail/logo.ico.go b/internal/mtail/logo.ico.go
deleted file mode 100755
index 1e0d9d445..000000000
--- a/internal/mtail/logo.ico.go
+++ /dev/null
@@ -1,2008 +0,0 @@
-package mtail
-
-var logoFavicon = []byte{
- // 32038 bytes from internal/mtail/logo.ico
- 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x40, 0x40, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x28, 0x42,
- 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0xa8, 0x25,
- 0x00, 0x00, 0x6e, 0x42, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0xa8, 0x10,
- 0x00, 0x00, 0x16, 0x68, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x68, 0x04,
- 0x00, 0x00, 0xbe, 0x78, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x13, 0x0b,
- 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0x81, 0xda, 0x97, 0x33, 0x1c, 0xda, 0x97, 0x33, 0x00, 0xd7, 0x94, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xd3, 0xdb, 0x98, 0x34, 0x8f, 0xda, 0x97, 0x33, 0x15, 0xdc, 0x99, 0x35, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xf6, 0xda, 0x97, 0x33, 0x8e, 0xda, 0x97, 0x33, 0x14, 0xda, 0x97,
- 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xda, 0x97, 0x33, 0x8e, 0xda, 0x97,
- 0x33, 0x16, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98,
- 0x34, 0x8e, 0xda, 0x97, 0x33, 0x15, 0xdb, 0x98, 0x34, 0x00, 0xdc, 0x99, 0x35, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf4, 0xdb, 0x98, 0x34, 0x8e, 0xda, 0x97, 0x33, 0x14, 0xdb, 0x98, 0x34, 0x00, 0xd6, 0x93,
- 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0x8e, 0xda, 0x97, 0x33, 0x15, 0xda, 0x97,
- 0x33, 0x00, 0xd8, 0x95, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x31, 0x00, 0xda, 0x99, 0x2f, 0x02, 0xdb, 0x98,
- 0x33, 0x10, 0xdb, 0x98, 0x34, 0x1a, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x41, 0xdb, 0x98,
- 0x34, 0xe2, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0x8e, 0xda, 0x97,
- 0x33, 0x16, 0xdb, 0x98, 0x34, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xa0, 0x02, 0x00, 0xdc, 0x97,
- 0x3b, 0x00, 0xdb, 0x99, 0x32, 0x08, 0xdb, 0x97, 0x33, 0x36, 0xdb, 0x98, 0x33, 0x6c, 0xdb, 0x98,
- 0x34, 0xa3, 0xdb, 0x98, 0x34, 0xc2, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98,
- 0x34, 0xfa, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xda, 0x97,
- 0x33, 0x8e, 0xda, 0x97, 0x33, 0x15, 0xda, 0x98, 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x97, 0x33, 0x01, 0xdb, 0x99,
- 0x33, 0x2a, 0xdb, 0x98, 0x33, 0x8d, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0xfa, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf5, 0xda, 0x97, 0x33, 0x89, 0xda, 0x97, 0x33, 0x0c, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x9a, 0x32, 0x00, 0xdd, 0x9c, 0x30, 0x02, 0xdb, 0x98, 0x33, 0x42, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf5, 0xda, 0x98, 0x33, 0x88, 0xda, 0x98, 0x33, 0x0c, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xaf, 0x26, 0x00, 0xda, 0x96, 0x34, 0x00, 0xdc, 0x99,
- 0x33, 0x07, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x97, 0x34, 0x08, 0xdb, 0x97,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xaf, 0x26, 0x00, 0xda, 0x96, 0x34, 0x00, 0xdc, 0x99,
- 0x33, 0x07, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x97, 0x34, 0x08, 0xdb, 0x97,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x96,
- 0x35, 0x00, 0xdc, 0x9a, 0x32, 0x00, 0xdb, 0x97, 0x34, 0x39, 0xdb, 0x98, 0x34, 0xcd, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xfa, 0xdb, 0x98, 0x34, 0xeb, 0xdb, 0x98, 0x34, 0xe2, 0xdb, 0x98, 0x34, 0xe2, 0xdb, 0x98,
- 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98,
- 0x34, 0x8d, 0xda, 0x98, 0x33, 0x15, 0xda, 0x97, 0x33, 0x00, 0xda, 0x99, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x99, 0x33, 0x00, 0xdb, 0x99, 0x32, 0x07, 0xdb, 0x98,
- 0x33, 0x67, 0xdb, 0x98, 0x34, 0xd1, 0xdb, 0x98, 0x34, 0xd4, 0xdb, 0x98, 0x34, 0x69, 0xdc, 0x99,
- 0x32, 0x07, 0xdb, 0x99, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x99, 0x33, 0x00, 0xdb, 0x99, 0x32, 0x07, 0xdb, 0x98,
- 0x33, 0x67, 0xdb, 0x98, 0x34, 0xd1, 0xdb, 0x98, 0x34, 0xd4, 0xdb, 0x98, 0x34, 0x69, 0xdc, 0x99,
- 0x32, 0x07, 0xdb, 0x99, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x8f, 0x24, 0x00, 0xda, 0x98,
- 0x34, 0x00, 0xdc, 0x97, 0x32, 0x16, 0xdb, 0x98, 0x34, 0xab, 0xdb, 0x98, 0x34, 0xfe, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfa, 0xdb, 0x98, 0x34, 0xc4, 0xdb, 0x98,
- 0x34, 0x80, 0xdb, 0x99, 0x34, 0x49, 0xdc, 0x98, 0x34, 0x2a, 0xdb, 0x98, 0x34, 0x41, 0xdb, 0x98,
- 0x34, 0xe2, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0x8d, 0xda, 0x98,
- 0x33, 0x15, 0xda, 0x98, 0x33, 0x00, 0xd9, 0x98, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x1f, 0xdb, 0x98,
- 0x34, 0xd1, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xcf, 0xdb, 0x98,
- 0x33, 0x1f, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x1f, 0xdb, 0x98,
- 0x34, 0xd1, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xcf, 0xdb, 0x98,
- 0x33, 0x1f, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0x32, 0x00, 0xd7, 0x92,
- 0x2a, 0x00, 0xdb, 0x98, 0x33, 0x60, 0xdb, 0x98, 0x34, 0xf0, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x95, 0xda, 0x98, 0x33, 0x23, 0xd8, 0x9c,
- 0x2c, 0x01, 0xe0, 0x9c, 0x2c, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xda, 0x98, 0x33, 0x8d, 0xda, 0x98, 0x33, 0x14, 0xda, 0x98,
- 0x33, 0x00, 0xd9, 0x98, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x99, 0x31, 0x00, 0xdb, 0x9a, 0x32, 0x00, 0xdb, 0x9a,
- 0x32, 0x11, 0xdb, 0x98, 0x34, 0xae, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xfe, 0xdb, 0x98, 0x34, 0xa7, 0xdb, 0x98, 0x34, 0x19, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf5, 0xda, 0x98, 0x33, 0x8e, 0xda, 0x98, 0x33, 0x14, 0xdb, 0x98, 0x34, 0x00, 0xd8, 0x98,
- 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x33, 0x3f, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xde, 0xdc, 0x98, 0x33, 0x41, 0xd9, 0x98, 0x35, 0x00, 0xe4, 0x96, 0x2d, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98,
- 0x34, 0x8d, 0xda, 0x98, 0x33, 0x15, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x98, 0x33, 0x00, 0xd7, 0x98, 0x37, 0x00, 0xdb, 0x98,
- 0x34, 0x69, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xa8, 0xdd, 0x97, 0x32, 0x0b, 0xdd, 0x97, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xda, 0x98, 0x33, 0x8d, 0xda, 0x98,
- 0x33, 0x15, 0xda, 0x98, 0x33, 0x00, 0xdc, 0x98, 0x35, 0x00, 0xdc, 0x98, 0x35, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdb, 0x96, 0x33, 0x0b, 0xdb, 0x98,
- 0x34, 0x94, 0xdb, 0x98, 0x34, 0xfe, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfa, 0xda, 0x98,
- 0x33, 0x7c, 0xd9, 0x97, 0x31, 0x01, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xf7, 0xdb, 0x98, 0x34, 0x8d, 0xda, 0x98, 0x33, 0x14, 0xda, 0x98,
- 0x33, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x16, 0xdb, 0x97,
- 0x34, 0xb4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xee, 0xdb, 0x98,
- 0x33, 0x52, 0xdc, 0x97, 0x37, 0x00, 0xdb, 0x98, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x26, 0xdb, 0x98,
- 0x34, 0xd5, 0xdb, 0x98, 0x34, 0x90, 0xda, 0x98, 0x33, 0x15, 0xdb, 0x98, 0x34, 0x00, 0xd9, 0x98,
- 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x1c, 0xdb, 0x98,
- 0x34, 0xc9, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe7, 0xdb, 0x98,
- 0x34, 0x3b, 0xdb, 0x99, 0x34, 0x00, 0xdb, 0x96, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x1c, 0xda, 0x98,
- 0x33, 0x72, 0xda, 0x98, 0x33, 0x18, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0xda, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98,
- 0x34, 0x27, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x96, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x03, 0xda, 0x98,
- 0x33, 0x09, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x24, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xd9, 0x9b, 0x2e, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x29, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xd7, 0xdb, 0x98,
- 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x32, 0x00, 0xdb, 0x98, 0x35, 0x00, 0xdb, 0x98, 0x33, 0x3d, 0xdb, 0x98,
- 0x34, 0xe5, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xd3, 0xdb, 0x98,
- 0x33, 0x20, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x98,
- 0x34, 0x24, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x34, 0xdb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xd8, 0x9b, 0x36, 0x00, 0xdb, 0x98, 0x34, 0x50, 0xdb, 0x98,
- 0x34, 0xeb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x33, 0x2a, 0xdb, 0x98, 0x35, 0x00, 0xd8, 0x9e, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xd9, 0x9c, 0x2c, 0x00, 0xdb, 0x97, 0x35, 0x00, 0xdb, 0x98, 0x33, 0x29, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x33, 0x2a, 0xdb, 0x98, 0x35, 0x00, 0xd8, 0x9e, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xd9, 0x9c, 0x2c, 0x00, 0xdb, 0x97, 0x35, 0x00, 0xdb, 0x98, 0x33, 0x29, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xd7, 0xdb, 0x98,
- 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdc, 0x98, 0x34, 0x00, 0xdc, 0x98, 0x33, 0x02, 0xdb, 0x98, 0x34, 0x7b, 0xdb, 0x98,
- 0x34, 0xf8, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xec, 0xdb, 0x98,
- 0x33, 0x4c, 0xdd, 0x98, 0x38, 0x00, 0xda, 0x98, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x98, 0x31, 0x00, 0xde, 0x99, 0x38, 0x00, 0xdb, 0x98, 0x33, 0x4c, 0xdb, 0x98,
- 0x34, 0xea, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xec, 0xdb, 0x98,
- 0x33, 0x4c, 0xdd, 0x98, 0x38, 0x00, 0xda, 0x98, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x98, 0x31, 0x00, 0xde, 0x99, 0x38, 0x00, 0xdb, 0x98, 0x33, 0x4c, 0xdb, 0x98,
- 0x34, 0xea, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xc1, 0xda, 0x97,
- 0x34, 0x1a, 0xdb, 0x97, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x32, 0x00, 0xdb, 0x98, 0x32, 0x10, 0xdb, 0x98, 0x33, 0xab, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x97,
- 0x34, 0x92, 0xdb, 0x97, 0x34, 0x07, 0xdb, 0x97, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdb, 0x97, 0x34, 0x08, 0xdb, 0x98, 0x34, 0x92, 0xdb, 0x98,
- 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x97,
- 0x34, 0x92, 0xdb, 0x97, 0x34, 0x07, 0xdb, 0x97, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdb, 0x97, 0x34, 0x08, 0xdb, 0x98, 0x34, 0x92, 0xdb, 0x98,
- 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfe, 0xdb, 0x98, 0x34, 0x96, 0xdc, 0x98,
- 0x32, 0x0d, 0xdc, 0x98, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x8a,
- 0x39, 0x00, 0xda, 0x98, 0x33, 0x00, 0xdb, 0x97, 0x34, 0x3f, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x33, 0x4a, 0xde, 0x99, 0x34, 0x01, 0xdc, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x97,
- 0x34, 0x00, 0xe1, 0x93, 0x36, 0x01, 0xdb, 0x98, 0x33, 0x4a, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x33, 0x4a, 0xde, 0x99, 0x34, 0x01, 0xdc, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x97,
- 0x34, 0x00, 0xe1, 0x93, 0x36, 0x01, 0xdb, 0x98, 0x33, 0x4a, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf3, 0xda, 0x98, 0x33, 0x58, 0xdb, 0x95,
- 0x39, 0x00, 0xda, 0x9c, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x98,
- 0x33, 0x00, 0xda, 0x97, 0x33, 0x0a, 0xdb, 0x98, 0x34, 0x91, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xcc, 0xdb, 0x98, 0x33, 0x4a, 0xdb, 0x96, 0x34, 0x07, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x96, 0x34, 0x00, 0xdb, 0x96, 0x34, 0x00, 0xda, 0x98, 0x33, 0x00, 0xdb, 0x97,
- 0x34, 0x07, 0xdb, 0x98, 0x33, 0x49, 0xdb, 0x98, 0x34, 0xcc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xcc, 0xdb, 0x98, 0x33, 0x4a, 0xdb, 0x96, 0x34, 0x07, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x96, 0x34, 0x00, 0xdb, 0x96, 0x34, 0x00, 0xda, 0x98, 0x33, 0x00, 0xdb, 0x97,
- 0x34, 0x07, 0xdb, 0x98, 0x33, 0x49, 0xdb, 0x98, 0x34, 0xcc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x33, 0xbe, 0xda, 0x99, 0x32, 0x1f, 0xdb, 0x99,
- 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0x33, 0x00, 0xd9, 0x96,
- 0x32, 0x06, 0xda, 0x97, 0x33, 0x5f, 0xdb, 0x98, 0x34, 0xe8, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xf9, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x97, 0x34, 0x92, 0xdb, 0x98,
- 0x33, 0x4c, 0xdb, 0x98, 0x33, 0x29, 0xdb, 0x98, 0x33, 0x2a, 0xda, 0x98, 0x33, 0x4c, 0xdb, 0x98,
- 0x34, 0x91, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf5, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x97, 0x34, 0x92, 0xdb, 0x98,
- 0x33, 0x4c, 0xdb, 0x98, 0x33, 0x29, 0xdb, 0x98, 0x33, 0x2a, 0xda, 0x98, 0x33, 0x4c, 0xdb, 0x98,
- 0x34, 0x91, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xeb, 0xdb, 0x98, 0x33, 0x5d, 0xda, 0x9b, 0x30, 0x01, 0xdb, 0x99,
- 0x33, 0x00, 0xdb, 0x99, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x98, 0x33, 0x00, 0xde, 0x98, 0x32, 0x05, 0xdb, 0x98,
- 0x33, 0x59, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x33, 0xc9, 0xdb, 0x98, 0x34, 0x9b, 0xdb, 0x98, 0x34, 0xf1, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98,
- 0x34, 0xec, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xec, 0xdb, 0x98,
- 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf2, 0xdb, 0x98, 0x34, 0x8a, 0xdb, 0x98, 0x34, 0x8a, 0xdb, 0x98, 0x34, 0xf2, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98,
- 0x34, 0xec, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xec, 0xdb, 0x98,
- 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf4, 0xdb, 0x98, 0x34, 0x83, 0xdc, 0x98, 0x34, 0x0c, 0xda, 0x97, 0x34, 0x00, 0xe6, 0xa0,
- 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x33, 0x1d, 0xdb, 0x98,
- 0x34, 0xc9, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xe5, 0xdb, 0x98, 0x33, 0x53, 0xda, 0x98, 0x32, 0x15, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98,
- 0x34, 0xea, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xeb, 0xdb, 0x98,
- 0x34, 0x83, 0xda, 0x98, 0x33, 0x14, 0xda, 0x98, 0x33, 0x14, 0xdb, 0x98, 0x34, 0x83, 0xdb, 0x98,
- 0x34, 0xeb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xeb, 0xdb, 0x98,
- 0x34, 0x83, 0xda, 0x98, 0x33, 0x15, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xd5, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xed, 0xdb, 0x98,
- 0x34, 0x72, 0xdc, 0x9a, 0x32, 0x09, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x34, 0x0c, 0xdb, 0x98,
- 0x34, 0x59, 0xdb, 0x98, 0x34, 0xc1, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0xc1, 0xdb, 0x98, 0x33, 0x5e, 0xdc, 0x99,
- 0x34, 0x0d, 0xdc, 0x98, 0x34, 0x00, 0xdc, 0x99, 0x34, 0x00, 0xdc, 0x99, 0x34, 0x0d, 0xdb, 0x98,
- 0x33, 0x5e, 0xdb, 0x98, 0x34, 0xc1, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xfe, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xc0, 0xdb, 0x98, 0x33, 0x5d, 0xdc, 0x99,
- 0x34, 0x0d, 0xdc, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x98, 0x33, 0x00, 0xdc, 0x98, 0x33, 0x09, 0xdb, 0x98,
- 0x33, 0x6d, 0xdb, 0x98, 0x34, 0xd1, 0xdb, 0x98, 0x34, 0xc8, 0xdb, 0x98, 0x34, 0x66, 0xda, 0x9a,
- 0x34, 0x0b, 0xda, 0x99, 0x34, 0x00, 0xdb, 0x99, 0x34, 0x00, 0xde, 0x9e, 0x31, 0x00, 0xdd, 0x9f,
- 0x30, 0x01, 0xdb, 0x99, 0x33, 0x22, 0xdb, 0x98, 0x34, 0x60, 0xdb, 0x98, 0x34, 0x9c, 0xdb, 0x98,
- 0x34, 0xc9, 0xdb, 0x98, 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xc8, 0xdb, 0x98,
- 0x34, 0x9c, 0xdb, 0x98, 0x34, 0x5f, 0xdb, 0x99, 0x34, 0x23, 0xdb, 0x9a, 0x33, 0x01, 0xdb, 0x99,
- 0x33, 0x00, 0xdb, 0x99, 0x34, 0x00, 0xdb, 0x99, 0x34, 0x00, 0xde, 0x9d, 0x31, 0x00, 0xde, 0x9f,
- 0x30, 0x01, 0xdb, 0x99, 0x33, 0x22, 0xdb, 0x98, 0x34, 0x60, 0xdb, 0x98, 0x34, 0x9c, 0xdb, 0x98,
- 0x34, 0xc9, 0xdb, 0x98, 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xd6, 0xdb, 0x98, 0x34, 0xc1, 0xdb, 0x98,
- 0x34, 0x97, 0xdb, 0x98, 0x33, 0x5d, 0xdb, 0x99, 0x34, 0x22, 0xda, 0x9a, 0x33, 0x01, 0xda, 0x99,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x82, 0x00, 0x00, 0xd9, 0x99, 0x36, 0x00, 0xdc, 0x98,
- 0x31, 0x08, 0xdb, 0x98, 0x33, 0x1f, 0xdb, 0x98, 0x33, 0x1c, 0xdb, 0x98, 0x34, 0x05, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x02, 0xdb, 0x98, 0x34, 0x0e, 0xdb, 0x98,
- 0x34, 0x1c, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98, 0x34, 0x1c, 0xdb, 0x98,
- 0x34, 0x0e, 0xdc, 0x98, 0x35, 0x01, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x02, 0xdb, 0x98, 0x34, 0x0e, 0xdb, 0x98,
- 0x34, 0x1c, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x1a, 0xdb, 0x98,
- 0x33, 0x0d, 0xd9, 0x9d, 0x2d, 0x00, 0xda, 0x9b, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0x7f, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xe0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xe0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x05, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xc0, 0x00, 0x01, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0xc0, 0x00, 0x03, 0xfe, 0x07,
- 0xfe, 0x07, 0xff, 0x80, 0x00, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0x00, 0x60, 0x0f, 0xfe, 0x07,
- 0xfe, 0x07, 0xff, 0x01, 0xe0, 0x1f, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0x03, 0xe0, 0x3f, 0xfe, 0x07,
- 0xfe, 0x07, 0xff, 0x03, 0xe0, 0x5f, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x03, 0xe0, 0xbf, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xe1, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xe2, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xe3, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfe, 0x07,
- 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfc, 0x07, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0xff, 0xfc, 0x03,
- 0xfc, 0x03, 0xfc, 0x07, 0xff, 0xff, 0xfc, 0x01, 0xf8, 0x01, 0xf8, 0x0f, 0xff, 0xff, 0xf8, 0x00,
- 0xf0, 0x00, 0xf0, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00,
- 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x20,
- 0x00, 0x60, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x50, 0x00, 0xd0, 0x00, 0xff, 0xff, 0xff, 0xf0, 0xfc,
- 0x03, 0xfc, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x28, 0x00,
- 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x20, 0xdb, 0x98, 0x34, 0x7e, 0xda, 0x97, 0x33, 0x14, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97,
- 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x23, 0xdb, 0x98, 0x34, 0xd7, 0xdb, 0x98, 0x34, 0x8c, 0xda, 0x97, 0x33, 0x10, 0xda, 0x97,
- 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x23, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xf8, 0xdb, 0x98, 0x34, 0x8b, 0xda, 0x97,
- 0x33, 0x10, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x23, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98,
- 0x34, 0x8b, 0xda, 0x97, 0x33, 0x10, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x22, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x8b, 0xda, 0x97, 0x33, 0x10, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98,
- 0x32, 0x00, 0xdb, 0x98, 0x31, 0x02, 0xdb, 0x98, 0x33, 0x11, 0xdb, 0x98, 0x34, 0x1b, 0xdb, 0x98,
- 0x34, 0x3f, 0xdb, 0x98, 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x8b, 0xda, 0x97, 0x33, 0x10, 0xda, 0x97,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x99, 0x32, 0x00, 0xdb, 0x99, 0x31, 0x07, 0xdb, 0x98,
- 0x33, 0x3a, 0xdb, 0x98, 0x34, 0x83, 0xdb, 0x98, 0x34, 0xb7, 0xdb, 0x98, 0x34, 0xd4, 0xdb, 0x98,
- 0x34, 0xe2, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x8c, 0xda, 0x97,
- 0x33, 0x12, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x9b,
- 0x30, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdb, 0x99, 0x33, 0x15, 0xdb, 0x98, 0x33, 0x84, 0xdb, 0x98,
- 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xfe, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xec, 0xda, 0x98,
- 0x33, 0x4b, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0xa6, 0x2a, 0x00, 0xda, 0x96, 0x35, 0x00, 0xdb, 0x98,
- 0x33, 0x0b, 0xdb, 0x98, 0x34, 0x1e, 0xdb, 0x97, 0x34, 0x0c, 0xdb, 0x97, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0xa6, 0x2a, 0x00, 0xda, 0x96, 0x35, 0x00, 0xdb, 0x98,
- 0x33, 0x0b, 0xdb, 0x98, 0x34, 0x1e, 0xdb, 0x97, 0x34, 0x0c, 0xdb, 0x97, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x92, 0x3b, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x97, 0x34, 0x10, 0xdb, 0x98, 0x34, 0x99, 0xdb, 0x98, 0x34, 0xfa, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf7, 0xdb, 0x98, 0x34, 0xe6, 0xdb, 0x98,
- 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x8b, 0xda, 0x98,
- 0x33, 0x12, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x33, 0x0c, 0xdb, 0x98,
- 0x34, 0x8d, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98, 0x34, 0x8e, 0xdb, 0x98, 0x32, 0x0c, 0xdb, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x33, 0x0c, 0xdb, 0x98,
- 0x34, 0x8d, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98, 0x34, 0x8e, 0xdb, 0x98, 0x32, 0x0c, 0xdb, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x96, 0x31, 0x00, 0xdd, 0x92,
- 0x29, 0x01, 0xdb, 0x98, 0x33, 0x6a, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf8, 0xdb, 0x98, 0x34, 0xb1, 0xdb, 0x98, 0x34, 0x5f, 0xdb, 0x99, 0x34, 0x2f, 0xdb, 0x98,
- 0x34, 0x3f, 0xdb, 0x98, 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x8a, 0xda, 0x98, 0x33, 0x10, 0xda, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98, 0x33, 0x21, 0xdb, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98, 0x33, 0x21, 0xdb, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x9a, 0x30, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98,
- 0x33, 0x1d, 0xdb, 0x98, 0x34, 0xca, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98,
- 0x34, 0x94, 0xda, 0x98, 0x33, 0x13, 0xdb, 0x96, 0x36, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x22, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf6, 0xdb, 0x98, 0x34, 0x8a, 0xda, 0x98, 0x33, 0x10, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x58, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xc9, 0xdc, 0x98,
- 0x33, 0x22, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x23, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98,
- 0x34, 0x8a, 0xda, 0x98, 0x33, 0x10, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdc, 0x97, 0x33, 0x03, 0xdb, 0x98,
- 0x34, 0x8e, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0x80, 0xb8, 0x9f,
- 0x54, 0x00, 0xde, 0x97, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x23, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xf8, 0xdb, 0x98, 0x34, 0x8a, 0xda, 0x98,
- 0x33, 0x10, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x11, 0xdb, 0x98,
- 0x34, 0xb5, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf3, 0xdb, 0x98, 0x33, 0x53, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x24, 0xdb, 0x98, 0x34, 0xd8, 0xdb, 0x98, 0x34, 0x8c, 0xda, 0x98, 0x33, 0x0f, 0xda, 0x98,
- 0x33, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x33, 0x1a, 0xdb, 0x98,
- 0x34, 0xcd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe8, 0xdb, 0x98, 0x34, 0x35, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x1c, 0xda, 0x98, 0x33, 0x6f, 0xda, 0x98, 0x33, 0x11, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98,
- 0x33, 0x03, 0xda, 0x98, 0x33, 0x06, 0xda, 0x98, 0x33, 0x00, 0xd9, 0x98, 0x32, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x99, 0x30, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x29, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0x1f, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xdd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x3a, 0xdb, 0x98,
- 0x34, 0xe8, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98, 0x33, 0x22, 0xdb, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xd8, 0xa0, 0x26, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe0, 0xdb, 0x98, 0x34, 0x23, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xd8, 0xa0, 0x26, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0xde, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdc, 0x99, 0x33, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x5c, 0xdb, 0x98,
- 0x34, 0xf5, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xea, 0xdb, 0x98, 0x33, 0x3b, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x98, 0x30, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x3b, 0xdb, 0x98,
- 0x34, 0xe8, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xea, 0xdb, 0x98, 0x33, 0x3b, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x98, 0x30, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x3b, 0xdb, 0x98,
- 0x34, 0xe8, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xcd, 0xda, 0x98, 0x34, 0x1b, 0xdb, 0x98,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x97, 0x33, 0x00, 0xda, 0x97, 0x32, 0x05, 0xdb, 0x98, 0x34, 0x93, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98,
- 0x32, 0x03, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x32, 0x03, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98,
- 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98,
- 0x32, 0x03, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x98, 0x33, 0x00, 0xda, 0x98, 0x32, 0x03, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98,
- 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xa2, 0xdc, 0x98, 0x32, 0x0a, 0xdb, 0x98,
- 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x97, 0x34, 0x2b, 0xdb, 0x98, 0x34, 0xd7, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x34, 0x50, 0xdb, 0x98, 0x32, 0x03, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x99,
- 0x32, 0x00, 0xda, 0x98, 0x31, 0x03, 0xdb, 0x98, 0x34, 0x4f, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x34, 0x50, 0xdb, 0x98, 0x32, 0x03, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x99,
- 0x32, 0x00, 0xda, 0x98, 0x31, 0x03, 0xdb, 0x98, 0x34, 0x4f, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf5, 0xdb, 0x98, 0x33, 0x5c, 0xdb, 0x97, 0x34, 0x00, 0xd9, 0x9b,
- 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97,
- 0x33, 0x00, 0xda, 0x97, 0x33, 0x10, 0xdb, 0x98, 0x34, 0x96, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xfe, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98, 0x33, 0x3b, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x33, 0x3b, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xf4, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98, 0x33, 0x3b, 0xdb, 0x98, 0x34, 0x24, 0xdb, 0x98,
- 0x33, 0x3b, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xb4, 0xdb, 0x98, 0x33, 0x15, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x98, 0x33, 0x00, 0xdc, 0x98,
- 0x33, 0x09, 0xdb, 0x98, 0x34, 0x85, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf1, 0xdb, 0x98, 0x33, 0x8f, 0xdb, 0x98, 0x34, 0xca, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xea, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x34, 0xea, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xcb, 0xdb, 0x98, 0x34, 0x67, 0xdb, 0x98, 0x34, 0xca, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xea, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98,
- 0x34, 0xea, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xcd, 0xdb, 0x98, 0x34, 0x36, 0xd9, 0x97, 0x34, 0x00, 0xde, 0x9a, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x20, 0xdb, 0x98, 0x34, 0xda, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98,
- 0x34, 0x96, 0xdb, 0x98, 0x32, 0x0f, 0xdb, 0x98, 0x34, 0x34, 0xdb, 0x98, 0x34, 0xb2, 0xdb, 0x98,
- 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xb5, 0xdb, 0x98,
- 0x34, 0x36, 0xd4, 0x98, 0x2e, 0x01, 0xdb, 0x98, 0x34, 0x36, 0xdb, 0x98, 0x34, 0xb5, 0xdb, 0x98,
- 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf6, 0xdb, 0x98, 0x34, 0xb4, 0xdb, 0x98,
- 0x34, 0x36, 0xd2, 0x98, 0x2c, 0x00, 0xd9, 0x98, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x0e, 0xdb, 0x98, 0x34, 0x92, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0x90, 0xda, 0x99,
- 0x34, 0x18, 0xda, 0x98, 0x34, 0x00, 0xdb, 0x9c, 0x33, 0x00, 0xdb, 0x99, 0x33, 0x16, 0xdb, 0x98,
- 0x34, 0x61, 0xdb, 0x98, 0x34, 0xa8, 0xdb, 0x98, 0x34, 0xd2, 0xdb, 0x98, 0x34, 0xde, 0xdb, 0x98,
- 0x34, 0xd2, 0xdb, 0x98, 0x34, 0xa7, 0xdb, 0x98, 0x34, 0x61, 0xdb, 0x99, 0x33, 0x17, 0xd6, 0x93,
- 0x3b, 0x00, 0xdf, 0x9c, 0x31, 0x00, 0xc7, 0x8f, 0x40, 0x00, 0xdb, 0x99, 0x33, 0x17, 0xdb, 0x98,
- 0x34, 0x61, 0xdb, 0x98, 0x34, 0xa8, 0xdb, 0x98, 0x34, 0xd2, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98,
- 0x34, 0xcd, 0xdb, 0x98, 0x34, 0xa4, 0xdb, 0x98, 0x34, 0x61, 0xdb, 0x99, 0x33, 0x16, 0xd4, 0x92,
- 0x3a, 0x00, 0xde, 0x9c, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x8e, 0x16, 0x00, 0xd6, 0x9a,
- 0x39, 0x00, 0xdb, 0x98, 0x33, 0x0d, 0xdb, 0x98, 0x33, 0x1e, 0xdb, 0x99, 0x33, 0x0a, 0xda, 0x95,
- 0x34, 0x00, 0xfd, 0xd8, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x0c, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98,
- 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x0c, 0xdc, 0x98, 0x35, 0x00, 0xdc, 0x98, 0x35, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x0c, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0x1a, 0xdb, 0x98, 0x33, 0x0a, 0xdd, 0x92, 0x3c, 0x00, 0xda, 0x9a, 0x31, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x5f, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xfc, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xfc, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xe0, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0xfc, 0x7f, 0xc7, 0xfe, 0x00, 0x01, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xfc, 0x00, 0x03, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xfc, 0x0c, 0x07, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xfc, 0x1c, 0x0f, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3c, 0x1f, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3c, 0x2f, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3c, 0x7f, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3c, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f, 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf8, 0x3f,
- 0x83, 0xf8, 0x3f, 0xff, 0x00, 0x00, 0xf0, 0x1f, 0x01, 0xf0, 0x3f, 0xff, 0x00, 0x00, 0xf0, 0x0e,
- 0x00, 0xe0, 0x7f, 0xff, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xc0, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xc1, 0x80,
- 0x38, 0x03, 0xff, 0xff, 0x00, 0x00, 0xe3, 0xc0, 0x7c, 0x0f, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x13, 0x0b,
- 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98, 0x34, 0x7a, 0xda, 0x97, 0x33, 0x10, 0xda, 0x97,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0xd8, 0xdb, 0x98, 0x34, 0x88, 0xda, 0x97,
- 0x33, 0x0c, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xfa, 0xdb, 0x98,
- 0x34, 0x87, 0xda, 0x97, 0x33, 0x0c, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x8c, 0x2b, 0x00, 0xdb, 0x99, 0x33, 0x00, 0xdb, 0x98, 0x32, 0x04, 0xdb, 0x98,
- 0x34, 0x13, 0xdb, 0x98, 0x34, 0x3c, 0xdb, 0x98, 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf7, 0xdb, 0x98, 0x34, 0x87, 0xda, 0x97, 0x33, 0x0c, 0xda, 0x97, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x99,
- 0x33, 0x00, 0xdb, 0x99, 0x32, 0x02, 0xdb, 0x98, 0x33, 0x3a, 0xdb, 0x98, 0x34, 0x98, 0xdb, 0x98,
- 0x34, 0xcd, 0xdb, 0x98, 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf8, 0xdb, 0x98, 0x34, 0x83, 0xda, 0x97, 0x33, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x9b, 0x31, 0x00, 0xe0, 0xa5, 0x21, 0x00, 0xdb, 0x98,
- 0x34, 0x12, 0xdb, 0x98, 0x34, 0x12, 0xdf, 0x94, 0x2e, 0x00, 0xdc, 0x98, 0x32, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x9b, 0x31, 0x00, 0xe0, 0xa5, 0x21, 0x00, 0xdb, 0x98,
- 0x34, 0x12, 0xdb, 0x98, 0x34, 0x12, 0xdf, 0x94, 0x2e, 0x00, 0xdc, 0x98, 0x32, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdf, 0x8d,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x58, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf2, 0xdb, 0x98, 0x34, 0xe7, 0xdb, 0x98, 0x34, 0xfb, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xf8, 0xdb, 0x98, 0x34, 0x83, 0xda, 0x98, 0x33, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x12, 0xdb, 0x98,
- 0x34, 0xb0, 0xdb, 0x98, 0x34, 0xb0, 0xdb, 0x98, 0x33, 0x12, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x12, 0xdb, 0x98,
- 0x34, 0xb0, 0xdb, 0x98, 0x34, 0xb0, 0xdb, 0x98, 0x33, 0x12, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98,
- 0x33, 0x29, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0xfa, 0xdb, 0x98, 0x34, 0x9b, 0xdb, 0x98,
- 0x34, 0x3d, 0xdb, 0x98, 0x34, 0x3f, 0xdb, 0x98, 0x34, 0xe4, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xf7, 0xdb, 0x98, 0x34, 0x87, 0xda, 0x98, 0x33, 0x0c, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x97, 0x35, 0x00, 0xdb, 0x98,
- 0x34, 0x78, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98, 0x34, 0xab, 0xdb, 0x98, 0x33, 0x0f, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xf9, 0xdb, 0x98,
- 0x34, 0x87, 0xda, 0x98, 0x33, 0x0c, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x97, 0x34, 0x00, 0xdb, 0x97, 0x34, 0x09, 0xdb, 0x98,
- 0x34, 0xb4, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x33, 0x56, 0xda, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0x89, 0xda, 0x98,
- 0x33, 0x0c, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0x33, 0x00, 0xda, 0x97, 0x33, 0x18, 0xdb, 0x98,
- 0x34, 0xd3, 0xdb, 0x98, 0x34, 0xec, 0xdb, 0x98, 0x34, 0x31, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x1c, 0xdb, 0x98, 0x34, 0x6b, 0xda, 0x98, 0x33, 0x0e, 0xda, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe0, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xda, 0x98,
- 0x33, 0x00, 0xda, 0x98, 0x33, 0x03, 0xda, 0x98, 0x33, 0x05, 0xda, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe2, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe2, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x27, 0xdb, 0x98,
- 0x34, 0xe5, 0xdb, 0x98, 0x34, 0xdf, 0xdb, 0x98, 0x34, 0x1f, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe2, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x20, 0xdb, 0x98,
- 0x34, 0xe1, 0xdb, 0x98, 0x34, 0xe3, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x3f, 0xdb, 0x98,
- 0x34, 0xf1, 0xdb, 0x98, 0x34, 0xe8, 0xdb, 0x98, 0x33, 0x2d, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x2c, 0xdb, 0x98,
- 0x34, 0xe7, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98, 0x33, 0x2d, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x2c, 0xdb, 0x98,
- 0x34, 0xe8, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0x1c, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xda, 0x97, 0x33, 0x00, 0xdc, 0x9a, 0x36, 0x00, 0xdb, 0x98, 0x34, 0x79, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x99, 0x32, 0x02, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x31, 0x01, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x98,
- 0x34, 0xfc, 0xdb, 0x98, 0x34, 0xfc, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x99, 0x32, 0x02, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x31, 0x01, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xae, 0xdb, 0x98, 0x33, 0x09, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97,
- 0x33, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xda, 0x98, 0x33, 0x2a, 0xdb, 0x98, 0x34, 0xd2, 0xdb, 0x98,
- 0x34, 0xff, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x98,
- 0x33, 0x2b, 0xdb, 0x98, 0x33, 0x2b, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98,
- 0x34, 0xfa, 0xdb, 0x98, 0x34, 0xfa, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x98,
- 0x33, 0x2b, 0xdb, 0x98, 0x33, 0x2b, 0xdb, 0x98, 0x34, 0x76, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98,
- 0x34, 0xf3, 0xdb, 0x98, 0x33, 0x56, 0xdb, 0x98, 0x35, 0x00, 0xda, 0x99, 0x32, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98,
- 0x33, 0x00, 0xdb, 0x98, 0x33, 0x10, 0xdb, 0x98, 0x34, 0xb3, 0xdb, 0x98, 0x34, 0xff, 0xdb, 0x98,
- 0x34, 0xb7, 0xdb, 0x98, 0x34, 0x8d, 0xdb, 0x98, 0x34, 0xf2, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98,
- 0x34, 0xe9, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xf3, 0xdb, 0x98,
- 0x34, 0x86, 0xdb, 0x98, 0x34, 0x86, 0xdb, 0x98, 0x34, 0xf3, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98,
- 0x34, 0xe9, 0xdb, 0x98, 0x34, 0xe9, 0xdb, 0x98, 0x34, 0xfd, 0xdb, 0x98, 0x34, 0xf3, 0xdb, 0x98,
- 0x34, 0x81, 0xdb, 0x98, 0x33, 0x08, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x34, 0x14, 0xdb, 0x98, 0x34, 0xb2, 0xdb, 0x98, 0x34, 0xba, 0xdb, 0x98,
- 0x34, 0x2d, 0xdb, 0x98, 0x34, 0x07, 0xdb, 0x98, 0x34, 0x56, 0xdb, 0x98, 0x34, 0xb2, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xb2, 0xdb, 0x98, 0x34, 0x57, 0xdb, 0x98,
- 0x33, 0x08, 0xdb, 0x99, 0x34, 0x08, 0xdb, 0x98, 0x34, 0x57, 0xdb, 0x98, 0x34, 0xb2, 0xdb, 0x98,
- 0x34, 0xdc, 0xdb, 0x98, 0x34, 0xd9, 0xdb, 0x98, 0x34, 0xb0, 0xdb, 0x98, 0x34, 0x57, 0xdb, 0x98,
- 0x34, 0x09, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x97,
- 0x31, 0x00, 0xe1, 0x96, 0x2d, 0x00, 0xdb, 0x98, 0x33, 0x13, 0xdb, 0x98, 0x33, 0x11, 0x00, 0x00,
- 0xff, 0x00, 0xda, 0x9a, 0x32, 0x00, 0xe1, 0x98, 0x3a, 0x00, 0xdb, 0x98, 0x34, 0x0b, 0xdb, 0x98,
- 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x0a, 0xe1, 0x98, 0x3a, 0x00, 0xd8, 0x98,
- 0x31, 0x00, 0xd8, 0x98, 0x31, 0x00, 0xe1, 0x98, 0x3a, 0x00, 0xdb, 0x98, 0x34, 0x0b, 0xdb, 0x98,
- 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x1c, 0xdb, 0x98, 0x33, 0x09, 0xdc, 0x97, 0x3b, 0x00, 0xdb, 0x98,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
- 0xff, 0x8f, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xff,
- 0xf8, 0x00, 0xe1, 0xe1, 0xf0, 0x00, 0xe1, 0xe1, 0xf0, 0x01, 0xe1, 0xe1, 0xf0, 0x83, 0xe1, 0xe1,
- 0xe1, 0x87, 0xe1, 0xe1, 0xe1, 0x8f, 0xe1, 0xe1, 0xe1, 0x9f, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1,
- 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1,
- 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1,
- 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xe0, 0xc0,
- 0xc1, 0xff, 0xc0, 0x00, 0x03, 0xff, 0x80, 0x00, 0x03, 0xff, 0x80, 0x00, 0x07, 0xff, 0x8e, 0x1e,
- 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x28, 0x00,
- 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x1f, 0xdb, 0x98, 0x34, 0x75, 0xdb, 0x98,
- 0x34, 0x0d, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x9b, 0x2a, 0x00, 0xdb, 0x98,
- 0x34, 0x00, 0xdb, 0x98, 0x33, 0x05, 0xdb, 0x98, 0x34, 0x38, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98,
- 0x34, 0x84, 0xdb, 0x98, 0x34, 0x0c, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x33, 0x02, 0xdb, 0x98,
- 0x34, 0x12, 0xdb, 0x98, 0x34, 0x02, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x33, 0x02, 0xdb, 0x98,
- 0x34, 0x12, 0xdb, 0x98, 0x34, 0x02, 0xdb, 0x98, 0x33, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98,
- 0x34, 0x22, 0xdb, 0x98, 0x34, 0x9f, 0xdb, 0x98, 0x34, 0xcb, 0xdb, 0x98, 0x34, 0xf9, 0xdb, 0x98,
- 0x34, 0xec, 0xdb, 0x98, 0x34, 0x4d, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x1a, 0xdb, 0x98,
- 0x34, 0xa1, 0xdb, 0x98, 0x34, 0x1b, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x1a, 0xdb, 0x98,
- 0x34, 0xa1, 0xdb, 0x98, 0x34, 0x1b, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x33, 0x02, 0xdb, 0x98,
- 0x34, 0x96, 0xdb, 0x98, 0x34, 0x98, 0xdb, 0x98, 0x34, 0x46, 0xdb, 0x98, 0x34, 0xdd, 0xdb, 0x98,
- 0x34, 0x85, 0xda, 0x98, 0x33, 0x0c, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x17, 0xdb, 0x98,
- 0x34, 0xbf, 0xdb, 0x98, 0x34, 0x32, 0xdb, 0x98, 0x34, 0x18, 0xdb, 0x98, 0x34, 0x67, 0xdb, 0x98,
- 0x34, 0x0b, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xd2, 0x98, 0x2c, 0x00, 0xda, 0x98, 0x33, 0x04, 0xda, 0x98,
- 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc1, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc1, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x21, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x22, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x2a, 0xdb, 0x98,
- 0x34, 0xcb, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x25, 0xdb, 0x98,
- 0x34, 0xc8, 0xdb, 0x98, 0x34, 0x26, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x34, 0x26, 0xdb, 0x98,
- 0x34, 0xc2, 0xdb, 0x98, 0x34, 0x1f, 0xdb, 0x98, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x99, 0x36, 0x00, 0xdb, 0x98, 0x34, 0x68, 0xdb, 0x98,
- 0x34, 0xf2, 0xdb, 0x98, 0x34, 0x7f, 0xdb, 0x98, 0x34, 0x26, 0xdb, 0x98, 0x34, 0x7f, 0xdb, 0x98,
- 0x34, 0xee, 0xdb, 0x98, 0x34, 0x7f, 0xdb, 0x98, 0x34, 0x26, 0xdb, 0x98, 0x34, 0x82, 0xdb, 0x98,
- 0x34, 0xab, 0xdb, 0x98, 0x33, 0x0a, 0xdb, 0x98, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x15, 0xdb, 0x98, 0x34, 0xa1, 0xdb, 0x98,
- 0x34, 0x73, 0xdb, 0x98, 0x34, 0xa9, 0xdb, 0x98, 0x34, 0xc5, 0xdb, 0x98, 0x34, 0xaa, 0xdb, 0x98,
- 0x34, 0x5c, 0xdb, 0x98, 0x34, 0xaa, 0xdb, 0x98, 0x34, 0xc5, 0xdb, 0x98, 0x34, 0xac, 0xdb, 0x98,
- 0x34, 0x30, 0xdb, 0x98, 0x34, 0x00, 0xdb, 0x98, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x98, 0x34, 0x03, 0xdb, 0x98, 0x34, 0x12, 0xdb, 0x98,
- 0x34, 0x02, 0xdb, 0x98, 0x34, 0x0b, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x0b, 0xdb, 0x97,
- 0x35, 0x00, 0xdb, 0x98, 0x34, 0x0b, 0xdb, 0x98, 0x34, 0x1d, 0xdb, 0x98, 0x34, 0x0b, 0xdb, 0x98,
- 0x35, 0x00, 0xd9, 0x99, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x88, 0xc0,
- 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x88, 0x81, 0x00, 0x00, 0x88, 0x83, 0x00, 0x00, 0x88, 0x8f,
- 0x00, 0x00, 0x88, 0x8f, 0x00, 0x00, 0x88, 0x8f, 0x00, 0x00, 0x88, 0x8f, 0x00, 0x00, 0x88, 0x8f,
- 0x00, 0x00, 0x88, 0x8f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x3f,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
-}
diff --git a/internal/mtail/mtail.go b/internal/mtail/mtail.go
index 073cefdee..973c8252b 100644
--- a/internal/mtail/mtail.go
+++ b/internal/mtail/mtail.go
@@ -14,11 +14,11 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/exporter"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime"
- "github.com/google/mtail/internal/tailer"
+ "github.com/jaqx0r/mtail/internal/exporter"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime"
+ "github.com/jaqx0r/mtail/internal/tailer"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
vc "github.com/prometheus/client_golang/prometheus/collectors/version"
@@ -69,6 +69,7 @@ func (m *Server) initRuntime() (err error) {
// initExporter sets up an Exporter for this Server.
func (m *Server) initExporter() (err error) {
+ m.eOpts = append(m.eOpts, exporter.Version(m.buildInfo.Version))
m.e, err = exporter.New(m.ctx, m.store, m.eOpts...)
if err != nil {
return err
@@ -193,6 +194,7 @@ func New(ctx context.Context, store *metrics.Store, options ...Option) (*Server,
"log_lines_total": prometheus.NewDesc("log_lines_total", "number of lines read per log file", []string{"logfile"}, nil),
// internal/runtime/loader.go
"lines_total": prometheus.NewDesc("lines_total", "number of lines received by the program loader", nil, nil),
+ "prog_lines_total": prometheus.NewDesc("prog_lines_total", "number of lines read per program", []string{"prog"}, nil),
"prog_loads_total": prometheus.NewDesc("prog_loads_total", "number of program load events by program source filename", []string{"prog"}, nil),
"prog_load_errors_total": prometheus.NewDesc("prog_load_errors_total", "number of errors encountered when loading per program source filename", []string{"prog"}, nil),
"prog_runtime_errors_total": prometheus.NewDesc("prog_runtime_errors_total", "number of errors encountered when executing programs per source filename", []string{"prog"}, nil),
diff --git a/internal/mtail/multiple_levels_directory_integration_test.go b/internal/mtail/multiple_levels_directory_integration_test.go
index 416010404..729398cf3 100644
--- a/internal/mtail/multiple_levels_directory_integration_test.go
+++ b/internal/mtail/multiple_levels_directory_integration_test.go
@@ -8,8 +8,8 @@ import (
"path/filepath"
"testing"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestPollLogPathPatterns(t *testing.T) {
diff --git a/internal/mtail/multiple_lines_integration_test.go b/internal/mtail/multiple_lines_integration_test.go
index f3e3528e3..e8deae7b9 100644
--- a/internal/mtail/multiple_lines_integration_test.go
+++ b/internal/mtail/multiple_lines_integration_test.go
@@ -9,8 +9,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestMultipleLinesInOneWrite(t *testing.T) {
diff --git a/internal/mtail/options.go b/internal/mtail/options.go
index 350706261..6c353bfb2 100644
--- a/internal/mtail/options.go
+++ b/internal/mtail/options.go
@@ -11,10 +11,10 @@ import (
"time"
"contrib.go.opencensus.io/exporter/jaeger"
- "github.com/google/mtail/internal/exporter"
- "github.com/google/mtail/internal/runtime"
- "github.com/google/mtail/internal/tailer"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/exporter"
+ "github.com/jaqx0r/mtail/internal/runtime"
+ "github.com/jaqx0r/mtail/internal/tailer"
+ "github.com/jaqx0r/mtail/internal/waker"
"go.opencensus.io/trace"
)
diff --git a/internal/mtail/partial_line_integration_test.go b/internal/mtail/partial_line_integration_test.go
index b35a4f921..fe8ac25f5 100644
--- a/internal/mtail/partial_line_integration_test.go
+++ b/internal/mtail/partial_line_integration_test.go
@@ -8,8 +8,8 @@ import (
"path/filepath"
"testing"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestPartialLineRead(t *testing.T) {
diff --git a/internal/mtail/permission_denied_integration_unix_test.go b/internal/mtail/permission_denied_integration_unix_test.go
index a7e2fcfca..5f070d8fe 100644
--- a/internal/mtail/permission_denied_integration_unix_test.go
+++ b/internal/mtail/permission_denied_integration_unix_test.go
@@ -10,8 +10,8 @@ import (
"path/filepath"
"testing"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
// TestPermissionDeniedOnLog is a unix-specific test because on Windows, it is
diff --git a/internal/mtail/prog_load_integration_test.go b/internal/mtail/prog_load_integration_test.go
index d5ebb55fd..c4f15c310 100644
--- a/internal/mtail/prog_load_integration_test.go
+++ b/internal/mtail/prog_load_integration_test.go
@@ -8,8 +8,8 @@ import (
"path/filepath"
"testing"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestNewProg(t *testing.T) {
diff --git a/internal/mtail/read_pipe_integration_unix_test.go b/internal/mtail/read_pipe_integration_unix_test.go
index 2f34fc89b..ed4fe253f 100644
--- a/internal/mtail/read_pipe_integration_unix_test.go
+++ b/internal/mtail/read_pipe_integration_unix_test.go
@@ -12,8 +12,8 @@ import (
"syscall"
"testing"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
"golang.org/x/sys/unix"
)
diff --git a/internal/mtail/relative_path_pattern_integration_test.go b/internal/mtail/relative_path_pattern_integration_test.go
index 0b972af51..ca6d2e60d 100644
--- a/internal/mtail/relative_path_pattern_integration_test.go
+++ b/internal/mtail/relative_path_pattern_integration_test.go
@@ -9,8 +9,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestRelativeLog(t *testing.T) {
diff --git a/internal/mtail/testing.go b/internal/mtail/testing.go
index a8be50214..d3aa60526 100644
--- a/internal/mtail/testing.go
+++ b/internal/mtail/testing.go
@@ -13,10 +13,10 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
const defaultDoOrTimeoutDeadline = 10 * time.Second
@@ -57,6 +57,7 @@ func TestMakeServer(tb testing.TB, patternWakers int, streamWakers int, options
expvar.Get("log_closes_total").(*expvar.Map).Init()
expvar.Get("file_truncates_total").(*expvar.Map).Init()
expvar.Get("prog_loads_total").(*expvar.Map).Init()
+ expvar.Get("prog_lines_total").(*expvar.Map).Init()
ctx, cancel := context.WithCancel(context.Background())
ts := &TestServer{
diff --git a/internal/mtail/unix_socket_export_integration_test.go b/internal/mtail/unix_socket_export_integration_test.go
index 1a71ba8f4..04e49beed 100644
--- a/internal/mtail/unix_socket_export_integration_test.go
+++ b/internal/mtail/unix_socket_export_integration_test.go
@@ -9,8 +9,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/mtail"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/mtail"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestBasicUNIXSockets(t *testing.T) {
diff --git a/internal/runtime/BUILD.bazel b/internal/runtime/BUILD.bazel
new file mode 100644
index 000000000..d4169b61b
--- /dev/null
+++ b/internal/runtime/BUILD.bazel
@@ -0,0 +1,38 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "runtime",
+ srcs = [
+ "httpstatus.go",
+ "options.go",
+ "runtime.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/logline",
+ "//internal/metrics",
+ "//internal/runtime/compiler",
+ "//internal/runtime/vm",
+ "@com_github_golang_glog//:glog",
+ "@com_github_pkg_errors//:errors",
+ "@com_github_prometheus_client_golang//prometheus",
+ ],
+)
+
+go_test(
+ name = "runtime_test",
+ size = "small",
+ srcs = [
+ "runtime_integration_test.go",
+ "runtime_test.go",
+ ],
+ embed = [":runtime"],
+ deps = [
+ "//internal/logline",
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/testutil",
+ "@com_github_golang_glog//:glog",
+ ],
+)
diff --git a/internal/runtime/code/BUILD.bazel b/internal/runtime/code/BUILD.bazel
new file mode 100644
index 000000000..8b2cbbd18
--- /dev/null
+++ b/internal/runtime/code/BUILD.bazel
@@ -0,0 +1,24 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "code",
+ srcs = [
+ "instr.go",
+ "object.go",
+ "opcodes.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/code",
+ visibility = ["//:__subpackages__"],
+ deps = ["//internal/metrics"],
+)
+
+go_test(
+ name = "code_test",
+ size = "small",
+ srcs = [
+ "instr_test.go",
+ "opcodes_test.go",
+ ],
+ embed = [":code"],
+ deps = ["//internal/testutil"],
+)
diff --git a/internal/runtime/code/instr_test.go b/internal/runtime/code/instr_test.go
index 0d9ce8b85..8975336e2 100644
--- a/internal/runtime/code/instr_test.go
+++ b/internal/runtime/code/instr_test.go
@@ -6,8 +6,8 @@ package code_test
import (
"testing"
- "github.com/google/mtail/internal/runtime/code"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/code"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestInstrString(t *testing.T) {
diff --git a/internal/runtime/code/object.go b/internal/runtime/code/object.go
index 14c070a88..5aebe04e3 100644
--- a/internal/runtime/code/object.go
+++ b/internal/runtime/code/object.go
@@ -6,13 +6,14 @@ package code
import (
"regexp"
- "github.com/google/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics"
)
// Object is the data and bytecode resulting from compiled program source.
type Object struct {
- Program []Instr // The program bytecode.
- Strings []string // Static strings.
- Regexps []*regexp.Regexp // Static regular expressions.
- Metrics []*metrics.Metric // Metrics accessible to this program.
+ Program []Instr // The program bytecode.
+ Strings []string // Static strings.
+ Regexps []*regexp.Regexp // Static regular expressions.
+ Metrics []*metrics.Metric // Metrics accessible to this program.
+ LogRestriction []string // logs this program can be used against - if empty can be applied to any log
}
diff --git a/internal/runtime/code/opcodes.go b/internal/runtime/code/opcodes.go
index b5358f9be..399c90ab9 100644
--- a/internal/runtime/code/opcodes.go
+++ b/internal/runtime/code/opcodes.go
@@ -78,6 +78,9 @@ const (
Subst
Rsubst
+ // Capture group queries.
+ Defined // Check if a capture group is defined.
+
lastOpcode
)
@@ -140,6 +143,7 @@ var opNames = map[Opcode]string{
Scmp: "scmp",
Subst: "subst",
Rsubst: "rsubst",
+ Defined: "defined",
}
func (o Opcode) String() string {
diff --git a/internal/runtime/compiler/BUILD.bazel b/internal/runtime/compiler/BUILD.bazel
new file mode 100644
index 000000000..c5598a6b9
--- /dev/null
+++ b/internal/runtime/compiler/BUILD.bazel
@@ -0,0 +1,27 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "compiler",
+ srcs = ["compiler.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/runtime/code",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/checker",
+ "//internal/runtime/compiler/codegen",
+ "//internal/runtime/compiler/opt",
+ "//internal/runtime/compiler/parser",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "compiler_test",
+ size = "small",
+ srcs = ["compiler_test.go"],
+ deps = [
+ ":compiler",
+ "//internal/testutil",
+ ],
+)
diff --git a/internal/runtime/compiler/ast/BUILD.bazel b/internal/runtime/compiler/ast/BUILD.bazel
new file mode 100644
index 000000000..c2c5710a1
--- /dev/null
+++ b/internal/runtime/compiler/ast/BUILD.bazel
@@ -0,0 +1,31 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "ast",
+ srcs = [
+ "ast.go",
+ "walk.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/ast",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics",
+ "//internal/runtime/compiler/position",
+ "//internal/runtime/compiler/symbol",
+ "//internal/runtime/compiler/types",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "ast_test",
+ size = "small",
+ srcs = ["walk_test.go"],
+ deps = [
+ ":ast",
+ "//internal/runtime/compiler/parser",
+ "//internal/runtime/compiler/position",
+ "//internal/runtime/compiler/types",
+ "//internal/testutil",
+ ],
+)
diff --git a/internal/runtime/compiler/ast/ast.go b/internal/runtime/compiler/ast/ast.go
index f952d0a05..0fc6ebac9 100644
--- a/internal/runtime/compiler/ast/ast.go
+++ b/internal/runtime/compiler/ast/ast.go
@@ -7,10 +7,10 @@ import (
"sync"
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/runtime/compiler/symbol"
- "github.com/google/mtail/internal/runtime/compiler/types"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/symbol"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
)
type Node interface {
@@ -296,6 +296,20 @@ func (n *PatternLit) Type() types.Type {
return types.Pattern
}
+// LogFilter represents a LOGFILTER construct in the AST.
+type LogFilter struct {
+ P position.Position // Position of the LOGFILTER keyword.
+ Filters []string // List of strings provided in the LOGFILTER.
+}
+
+func (n *LogFilter) Pos() *position.Position {
+ return &n.P
+}
+
+func (n *LogFilter) Type() types.Type {
+ return types.Pattern
+}
+
// PatternFragment holds a named pattern part.
type PatternFragment struct {
ID Node
diff --git a/internal/runtime/compiler/ast/walk.go b/internal/runtime/compiler/ast/walk.go
index 02427785c..1fd271ba1 100644
--- a/internal/runtime/compiler/ast/walk.go
+++ b/internal/runtime/compiler/ast/walk.go
@@ -81,7 +81,7 @@ func Walk(v Visitor, node Node) Node {
case *PatternFragment:
n.Expr = Walk(v, n.Expr)
- case *IDTerm, *CaprefTerm, *VarDecl, *StringLit, *IntLit, *FloatLit, *PatternLit, *NextStmt, *OtherwiseStmt, *DelStmt, *StopStmt:
+ case *LogFilter, *IDTerm, *CaprefTerm, *VarDecl, *StringLit, *IntLit, *FloatLit, *PatternLit, *NextStmt, *OtherwiseStmt, *DelStmt, *StopStmt:
// These nodes are terminals, thus have no children to walk.
default:
diff --git a/internal/runtime/compiler/ast/walk_test.go b/internal/runtime/compiler/ast/walk_test.go
index 6c2caae5d..90d588266 100644
--- a/internal/runtime/compiler/ast/walk_test.go
+++ b/internal/runtime/compiler/ast/walk_test.go
@@ -6,11 +6,11 @@ package ast_test
import (
"testing"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/runtime/compiler/types"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
type testNode struct{}
diff --git a/internal/runtime/compiler/checker/BUILD.bazel b/internal/runtime/compiler/checker/BUILD.bazel
new file mode 100644
index 000000000..00234ae1c
--- /dev/null
+++ b/internal/runtime/compiler/checker/BUILD.bazel
@@ -0,0 +1,32 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "checker",
+ srcs = ["checker.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/checker",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/errors",
+ "//internal/runtime/compiler/parser",
+ "//internal/runtime/compiler/symbol",
+ "//internal/runtime/compiler/types",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "checker_test",
+ size = "small",
+ srcs = ["checker_test.go"],
+ deps = [
+ ":checker",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/parser",
+ "//internal/runtime/compiler/symbol",
+ "//internal/runtime/compiler/types",
+ "//internal/testutil",
+ "@com_github_google_go_cmp//cmp/cmpopts",
+ ],
+)
diff --git a/internal/runtime/compiler/checker/checker.go b/internal/runtime/compiler/checker/checker.go
index dcef8550e..e6bc0d117 100644
--- a/internal/runtime/compiler/checker/checker.go
+++ b/internal/runtime/compiler/checker/checker.go
@@ -10,12 +10,12 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/errors"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/runtime/compiler/symbol"
- "github.com/google/mtail/internal/runtime/compiler/types"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/symbol"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
)
const (
@@ -54,7 +54,7 @@ func Check(node ast.Node, maxRegexpLength int, maxRecursionDepth int) (ast.Node,
c := &checker{maxRegexLength: maxRegexpLength, maxRecursionDepth: maxRecursionDepth}
node = ast.Walk(c, node)
if len(c.errors) > 0 {
- return node, c.errors
+ return node, &c.errors
}
return node, nil
}
@@ -113,7 +113,6 @@ func (c *checker) VisitBefore(node ast.Node) (ast.Visitor, ast.Node) {
case *ast.VarDecl:
n.Symbol = symbol.NewSymbol(n.Name, symbol.VarSymbol, n.Pos())
if alt := c.scope.Insert(n.Symbol); alt != nil {
- c.errors.Add(n.Pos(), fmt.Sprintf("Redeclaration of metric `%s' previously declared at %s", n.Name, alt.Pos))
c.depth--
return nil, n
}
@@ -248,22 +247,7 @@ func (c *checker) VisitBefore(node ast.Node) (ast.Visitor, ast.Node) {
// checkSymbolTable emits errors if any eligible symbols in the current scope
// are not marked as used or have an invalid type.
func (c *checker) checkSymbolTable() {
- for _, sym := range c.scope.Symbols {
- if !sym.Used {
- // Users don't have control over the patterns given from decorators
- // so this should never be an error; but it can be useful to know
- // if a program is doing unnecessary work.
- if sym.Kind == symbol.CaprefSymbol {
- if sym.Addr == 0 {
- // Don't warn about the zeroth capture group; it's not user-defined.
- continue
- }
- glog.Infof("capture group reference `%s' at %s appears to be unused", sym.Name, sym.Pos)
- continue
- }
- c.errors.Add(sym.Pos, fmt.Sprintf("Declaration of %s `%s' here is never used.", sym.Kind, sym.Name))
- }
- }
+ c.scope.Check(&c.errors)
}
// VisitAfter performs the type annotation and checking, once the child nodes
@@ -292,6 +276,10 @@ func (c *checker) VisitAfter(node ast.Node) ast.Node {
switch n.Cond.(type) {
case *ast.BinaryExpr, *ast.OtherwiseStmt, *ast.UnaryExpr:
// OK as conditions
+ case *ast.BuiltinExpr:
+ if !types.Equals(n.Cond.Type(), types.Bool) {
+ c.errors.Add(n.Cond.Pos(), fmt.Sprintf("Can't interpret %s as a boolean expression here.\n\tTry using comparison operators to make the condition explicit.", n.Cond.Type()))
+ }
case *ast.PatternExpr:
// If the parser saw an IDTerm with type Pattern, then we know it's really a pattern constant and need to wrap it in an unary match in this context.
cond := &ast.UnaryExpr{Expr: n.Cond, Op: parser.MATCH}
@@ -838,6 +826,12 @@ func (c *checker) VisitAfter(node ast.Node) ast.Node {
n.SetType(types.Error)
return n
}
+ case "defined":
+ if _, ok := n.Args.(*ast.ExprList).Children[0].(*ast.CaprefTerm); !ok {
+ c.errors.Add(n.Args.(*ast.ExprList).Children[0].Pos(), "defined() expects a capture group reference as its argument")
+ n.SetType(types.Error)
+ return n
+ }
}
return n
@@ -900,7 +894,16 @@ func (c *checker) checkRegex(pattern string, n ast.Node) {
sym.Binding = n
sym.Addr = i
if alt := c.scope.Insert(sym); alt != nil {
- c.errors.Add(n.Pos(), fmt.Sprintf("Redeclaration of capture group `%s' previously declared at %s", sym.Name, alt.Pos))
+ // If this is a numbered capref, we allow chained match
+ // expressions to each define the same implicit capture
+ // groups. The last pattern's binding is used at runtime
+ // ("last match wins").
+ if capref == "" {
+ alt.Binding = n
+ glog.Infof("Update of capref `%s' binding in chained match expression", sym.Name)
+ } else {
+ c.errors.Add(n.Pos(), fmt.Sprintf("Redeclaration of capture group `%s' previously declared at %s", sym.Name, alt.Pos))
+ }
// No return, let this loop collect all errors
}
if capref != "" {
diff --git a/internal/runtime/compiler/checker/checker_test.go b/internal/runtime/compiler/checker/checker_test.go
index 9b771465e..3683e077a 100644
--- a/internal/runtime/compiler/checker/checker_test.go
+++ b/internal/runtime/compiler/checker/checker_test.go
@@ -9,12 +9,12 @@ import (
"testing"
"github.com/google/go-cmp/cmp/cmpopts"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/checker"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/runtime/compiler/symbol"
- "github.com/google/mtail/internal/runtime/compiler/types"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/checker"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/symbol"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var checkerTestDebug = flag.Bool("checker_test_debug", false, "Turn on to log AST in tests")
@@ -78,8 +78,8 @@ var checkerInvalidPrograms = []struct {
"duplicate declaration",
"counter foo\ncounter foo\n",
[]string{
- "duplicate declaration:2:9-11: Redeclaration of metric `foo' previously declared at duplicate declaration:1:9-11",
"duplicate declaration:1:9-11: Declaration of variable `foo' here is never used.",
+ "duplicate declaration:2:9-11: Redeclaration of variable `foo' previously declared at duplicate declaration:1:9-11",
},
},
@@ -333,11 +333,6 @@ l++=l
[]string{"dec non var:1:1-16: Can't assign to expression; expecting a variable here."},
},
- // TODO(jaq): This is an instance of bug #190, the capref is ambiguous.
- // {"regexp with no zero capref",
- // `//||/;0/ {$0||// {}}
- // `, []string{"regexp with no zero capref:1:5-6: Nonexistent capref =."}},
-
{
"cmp to None",
`strptime("","")<5{}
@@ -521,6 +516,35 @@ const X /foo/
{"concat expr 2", `
const X /foo/
X {
+}`},
+ {"concat start with id plus regex", `
+const A /foo/
+A + /bar/ {
+}`},
+ {"concat start with id plus id", `
+const X /foo/
+const Y /bar/
+X + Y {
+}`},
+ {"concat start multi", `
+const X /foo/
+const Y /bar/
+X + Y + /baz/ {
+}`},
+ {"concat start match", `
+const X /foo/
+"" =~ X + /bar/ {
+}`},
+ {"const with id concat", `
+const A /foo/
+const B A + /bar/
+B {
+}`},
+ {"const with id id", `
+const A /foo/
+const B /bar/
+const C A + B
+C {
}`},
{"match expression 3", `
const X /foo/
@@ -578,6 +602,28 @@ N {
const N /n/
N && 1 {
}`},
+
+ {"const pattern with named capref as cond", `
+counter c
+const P /(?Pn)/
+P {
+ c++
+}`},
+
+ {"const pattern with positional capref as cond", `
+counter c
+const P /(n)/
+P {
+ c += $1
+}`},
+
+ {"const pattern in a binary expr in cond", `
+counter c
+const P /(?Pn)/
+P && 1 {
+ c++
+}`},
+
{"negative numbers in capture groups", `
gauge foo
/(?P-?\d+)/ {
@@ -595,6 +641,12 @@ subst(/\d+/, "d", "1234")
text value
value = subst(/[a-zA-Z]+/, "a", "1234abcd")
value = subst(/\d+/, "d", value)
+`},
+ {"chained match OR capref", `
+const X /x/
+// || X {
+ $0
+}
`},
}
diff --git a/internal/runtime/compiler/codegen/BUILD.bazel b/internal/runtime/compiler/codegen/BUILD.bazel
new file mode 100644
index 000000000..0088f6094
--- /dev/null
+++ b/internal/runtime/compiler/codegen/BUILD.bazel
@@ -0,0 +1,34 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "codegen",
+ srcs = ["codegen.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/codegen",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/runtime/code",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/errors",
+ "//internal/runtime/compiler/parser",
+ "//internal/runtime/compiler/position",
+ "//internal/runtime/compiler/symbol",
+ "//internal/runtime/compiler/types",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "codegen_test",
+ size = "small",
+ srcs = ["codegen_test.go"],
+ deps = [
+ ":codegen",
+ "//internal/runtime/code",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/checker",
+ "//internal/runtime/compiler/parser",
+ "//internal/testutil",
+ ],
+)
diff --git a/internal/runtime/compiler/codegen/codegen.go b/internal/runtime/compiler/codegen/codegen.go
index 30467b796..943d3792a 100644
--- a/internal/runtime/compiler/codegen/codegen.go
+++ b/internal/runtime/compiler/codegen/codegen.go
@@ -10,15 +10,15 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/runtime/code"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/errors"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/runtime/compiler/symbol"
- "github.com/google/mtail/internal/runtime/compiler/types"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/runtime/code"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/symbol"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
)
// codegen represents a code generator.
@@ -38,7 +38,7 @@ func CodeGen(name string, n ast.Node) (*code.Object, error) {
_ = ast.Walk(c, n)
c.writeJumps()
if len(c.errors) > 0 {
- return nil, c.errors
+ return nil, &c.errors
}
return &c.obj, nil
}
@@ -134,16 +134,16 @@ func (c *codegen) VisitBefore(node ast.Node) (ast.Visitor, ast.Node) {
if n.Buckets[0] > 0 {
m.Buckets = append(m.Buckets, datum.Range{0, n.Buckets[0]})
}
- min := n.Buckets[0]
- for _, max := range n.Buckets[1:] {
- if max <= min {
+ lo := n.Buckets[0]
+ for _, hi := range n.Buckets[1:] {
+ if hi <= lo {
c.errorf(n.Pos(), "buckets boundaries must be sorted")
return nil, n
}
- m.Buckets = append(m.Buckets, datum.Range{min, max})
- min = max
+ m.Buckets = append(m.Buckets, datum.Range{lo, hi})
+ lo = hi
}
- m.Buckets = append(m.Buckets, datum.Range{min, math.Inf(+1)})
+ m.Buckets = append(m.Buckets, datum.Range{lo, math.Inf(+1)})
if len(n.Keys) == 0 {
// Calling GetDatum here causes the storage to be allocated.
@@ -325,6 +325,36 @@ func (c *codegen) VisitBefore(node ast.Node) (ast.Visitor, ast.Node) {
c.obj.Program[pc].Opcode = code.Expire
}
+ case *ast.LogFilter:
+ // Emit the list of log filters into the LogRestriction object.
+ c.obj.LogRestriction = append(c.obj.LogRestriction, n.Filters...)
+ return nil, n
+
+ case *ast.BuiltinExpr:
+ if n.Name == "defined" {
+ // Don't walk children: defined() requires special codegen
+ // to avoid emitting Capref/S2i for its capref argument,
+ // which would cause a runtime error on undefined groups.
+ args := n.Args.(*ast.ExprList).Children
+ if len(args) != 1 {
+ c.errorf(n.Pos(), "defined expects 1 argument, got %d", len(args))
+ return nil, n
+ }
+ capref, ok := args[0].(*ast.CaprefTerm)
+ if !ok {
+ c.errorf(n.Pos(), "defined expects a capture group reference")
+ return nil, n
+ }
+ if capref.Symbol == nil || capref.Symbol.Binding == nil {
+ c.errorf(n.Pos(), "No regular expression bound to capref %q", capref.Name)
+ return nil, n
+ }
+ rn := capref.Symbol.Binding.(*ast.PatternExpr)
+ c.emit(n, code.Push, rn.Index)
+ c.emit(n, code.Defined, capref.Symbol.Addr)
+ return nil, n
+ }
+
case *ast.BinaryExpr:
switch n.Op {
case parser.AND:
diff --git a/internal/runtime/compiler/codegen/codegen_test.go b/internal/runtime/compiler/codegen/codegen_test.go
index 0f634da52..460523753 100644
--- a/internal/runtime/compiler/codegen/codegen_test.go
+++ b/internal/runtime/compiler/codegen/codegen_test.go
@@ -9,20 +9,21 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/runtime/code"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/checker"
- "github.com/google/mtail/internal/runtime/compiler/codegen"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/code"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/checker"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/codegen"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var codegenTestDebug = flag.Bool("codegen_test_debug", false, "Log ASTs and debugging information ")
var testCodeGenPrograms = []struct {
- name string
- source string
- prog []code.Instr // expected bytecode
+ name string
+ source string
+ prog []code.Instr // expected bytecode
+ expectedLogs []string
}{
// Composite literals require too many explicit conversions.
{
@@ -37,6 +38,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 1},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"count a",
@@ -50,6 +52,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 1},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"strptime and capref",
@@ -69,6 +72,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"strptime and named capref",
@@ -88,6 +92,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"inc by and set",
@@ -114,6 +119,7 @@ var testCodeGenPrograms = []struct {
{code.Iset, nil, 4},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"cond expr gt",
@@ -136,6 +142,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"cond expr lt",
@@ -158,6 +165,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"cond expr eq",
@@ -180,6 +188,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"cond expr le",
@@ -202,6 +211,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"cond expr ge",
@@ -224,6 +234,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"cond expr ne",
@@ -246,6 +257,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"nested cond",
@@ -276,6 +288,7 @@ var testCodeGenPrograms = []struct {
{code.Setmatched, true, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"deco",
@@ -301,6 +314,7 @@ var testCodeGenPrograms = []struct {
{code.Inc, nil, 8},
{code.Setmatched, true, 3},
},
+ nil,
},
{
"length",
@@ -319,6 +333,7 @@ var testCodeGenPrograms = []struct {
{code.Setmatched, false, 0},
{code.Setmatched, true, 0},
},
+ nil,
},
{
"bitwise", `
@@ -353,6 +368,7 @@ a = 1 >> 20
{code.Shr, nil, 5},
{code.Iset, nil, 5},
},
+ nil,
},
{
"pow", `
@@ -377,6 +393,7 @@ gauge a
{code.Iset, nil, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"indexed expr", `
@@ -389,6 +406,7 @@ a["string"]++
{code.Dload, 1, 2},
{code.Inc, nil, 2},
},
+ nil,
},
{
"strtol", `
@@ -399,6 +417,7 @@ strtol("deadbeef", 16)
{code.Push, int64(16), 1},
{code.S2i, 2, 1},
},
+ nil,
},
{
"float", `
@@ -407,6 +426,7 @@ strtol("deadbeef", 16)
[]code.Instr{
{code.Push, 20.0, 1},
},
+ nil,
},
{
"otherwise", `
@@ -424,6 +444,7 @@ otherwise {
{code.Inc, nil, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"cond else",
@@ -453,6 +474,7 @@ counter bar
{code.Dload, 0, 5},
{code.Inc, nil, 5},
},
+ nil,
},
{
"mod",
@@ -468,6 +490,7 @@ a = 3 % 1
{code.Imod, nil, 2},
{code.Iset, nil, 2},
},
+ nil,
},
{
"del", `
@@ -479,6 +502,7 @@ del a["string"]
{code.Mload, 0, 2},
{code.Del, 1, 2},
},
+ nil,
},
{
"del after", `
@@ -491,6 +515,7 @@ del a["string"] after 1h
{code.Mload, 0, 2},
{code.Expire, 1, 2},
},
+ nil,
},
{
"types", `
@@ -525,6 +550,7 @@ gauge f
{code.Fset, nil, 7},
{code.Setmatched, true, 6},
},
+ nil,
},
{
@@ -534,6 +560,7 @@ getfilename()
[]code.Instr{
{code.Getfilename, 0, 1},
},
+ nil,
},
{
@@ -558,6 +585,7 @@ getfilename()
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"string to int",
@@ -578,6 +606,7 @@ getfilename()
{code.Iset, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"int to float",
@@ -598,6 +627,7 @@ getfilename()
{code.Fset, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"string to float",
@@ -618,6 +648,7 @@ getfilename()
{code.Fset, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"float to string",
@@ -639,6 +670,7 @@ getfilename()
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"int to string",
@@ -660,6 +692,7 @@ getfilename()
{code.Inc, nil, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"nested comparisons",
@@ -703,6 +736,7 @@ getfilename()
{code.Setmatched, true, 2},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"string concat", `
@@ -725,6 +759,7 @@ counter f by s
{code.Inc, nil, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"add assign float", `
@@ -748,6 +783,7 @@ gauge foo
{code.Fset, nil, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"match expression", `
@@ -772,6 +808,7 @@ gauge foo
{code.Setmatched, true, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"negative match expression", `
@@ -797,6 +834,7 @@ gauge foo
{code.Setmatched, true, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"capref used in def", `
@@ -822,6 +860,7 @@ gauge foo
{code.Setmatched, false, 1},
{code.Setmatched, true, 1},
},
+ nil,
},
{
"binop arith type conversion", `
@@ -846,6 +885,7 @@ gauge var
{code.Fset, nil, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{
"binop compare type conversion", `
@@ -879,6 +919,7 @@ counter var
{code.Setmatched, true, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{"set string", `
text foo
@@ -895,7 +936,10 @@ text foo
{code.Capref, 1, 3},
{code.Sset, nil, 3},
{code.Setmatched, true, 2},
- }},
+ },
+ nil,
+ },
+
{
"concat to text", `
text foo
@@ -916,6 +960,7 @@ text foo
{code.Sset, nil, 3},
{code.Setmatched, true, 2},
},
+ nil,
},
{"decrement", `
counter i
@@ -929,7 +974,9 @@ counter i
{code.Dload, 0, 3},
{code.Dec, nil, 3},
{code.Setmatched, true, 2},
- }},
+ },
+ nil,
+ },
{"capref and settime", `
/(\d+)/ {
settime($1)
@@ -942,7 +989,9 @@ counter i
{code.S2i, nil, 2},
{code.Settime, 1, 2},
{code.Setmatched, true, 1},
- }},
+ },
+ nil,
+ },
{"cast to self", `
/(\d+)/ {
settime(int($1))
@@ -955,12 +1004,16 @@ settime(int($1))
{code.S2i, nil, 2},
{code.Settime, 1, 2},
{code.Setmatched, true, 1},
- }},
+ },
+ nil,
+ },
{"stop", `
stop
`, []code.Instr{
{code.Stop, nil, 1},
- }},
+ },
+ nil,
+ },
{"stop inside", `
// {
stop
@@ -971,8 +1024,73 @@ stop
{code.Setmatched, false, 1},
{code.Stop, nil, 2},
{code.Setmatched, true, 1},
- }},
-
+ },
+ nil,
+ },
+ {
+ "log_filter with new line",
+ `log_filter "/tmp/log1", "/tmp/log2"
+`,
+ nil,
+ []string{
+ "/tmp/log1",
+ "/tmp/log2",
+ },
+ },
+ {
+ "log_filter without new line",
+ `log_filter "/tmp/log1", "/tmp/log2"`,
+ nil,
+ []string{
+ "/tmp/log1",
+ "/tmp/log2",
+ },
+ },
+ {
+ "log_filter unquoted", // only works if the logfile is an ID ie a word
+ `log_filter tmplog1, tmplog2`,
+ nil,
+ []string{
+ "tmplog1",
+ "tmplog2",
+ },
+ },
+ {
+ "log_filter before clause",
+ `
+log_filter "/tmp/log1", "/tmp/log2"
+20.0
+`,
+ []code.Instr{
+ {code.Push, 20.0, 2},
+ },
+ []string{
+ "/tmp/log1",
+ "/tmp/log2",
+ },
+ },
+ {"log_filter after clause", `
+20.0
+log_filter "/tmp/log1", "/tmp/log2"
+`, []code.Instr{
+ {code.Push, 20.0, 1},
+ }, []string{
+ "/tmp/log1",
+ "/tmp/log2",
+ },
+ },
+ {
+ "log_filter additive use",
+ `log_filter tmplog1, tmplog2
+log_filter tmplog1, tmplog3`,
+ nil,
+ []string{
+ "tmplog1",
+ "tmplog2",
+ "tmplog1", // this is de-duplicated later before it is used in the runtime
+ "tmplog3",
+ },
+ },
{
"nested decorators",
`def b {
@@ -984,7 +1102,7 @@ stop
}
}
@b {
-}`, nil,
+}`, nil, nil,
},
{"negative numbers in capture groups", `
gauge foo
@@ -1007,7 +1125,9 @@ foo += $value_ms / 1000.0
{code.Fadd, nil, 3},
{code.Fset, nil, 3},
{code.Setmatched, true, 2},
- }},
+ },
+ nil,
+ },
{"substitution", `
gauge foo
/(\d+,\d)/ {
@@ -1026,7 +1146,9 @@ gauge foo
{code.S2i, nil, 3},
{code.Iset, nil, 3},
{code.Setmatched, true, 2},
- }},
+ },
+ nil,
+ },
{"const term as pattern", `
const A /n/
A && 1 {
@@ -1042,7 +1164,9 @@ A && 1 {
{code.Jnm, 10, 0},
{code.Setmatched, false, 0},
{code.Setmatched, true, 0},
- }},
+ },
+ nil,
+ },
}
func TestCodeGenFromSource(t *testing.T) {
@@ -1060,6 +1184,7 @@ func TestCodeGenFromSource(t *testing.T) {
testutil.FatalIfErr(t, err)
obj, err := codegen.CodeGen(tc.name, ast)
testutil.FatalIfErr(t, err)
+ testutil.ExpectNoDiff(t, tc.expectedLogs, obj.LogRestriction, testutil.AllowUnexported(code.Instr{}))
testutil.ExpectNoDiff(t, tc.prog, obj.Program, testutil.AllowUnexported(code.Instr{}))
})
diff --git a/internal/runtime/compiler/compiler.go b/internal/runtime/compiler/compiler.go
index be149e124..1dec726a2 100644
--- a/internal/runtime/compiler/compiler.go
+++ b/internal/runtime/compiler/compiler.go
@@ -8,12 +8,12 @@ import (
"path/filepath"
"github.com/golang/glog"
- "github.com/google/mtail/internal/runtime/code"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/checker"
- "github.com/google/mtail/internal/runtime/compiler/codegen"
- "github.com/google/mtail/internal/runtime/compiler/opt"
- "github.com/google/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/code"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/checker"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/codegen"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/opt"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
)
type Compiler struct {
diff --git a/internal/runtime/compiler/compiler_test.go b/internal/runtime/compiler/compiler_test.go
index 8a779eb60..5e4cc04f2 100644
--- a/internal/runtime/compiler/compiler_test.go
+++ b/internal/runtime/compiler/compiler_test.go
@@ -7,8 +7,8 @@ import (
"strings"
"testing"
- "github.com/google/mtail/internal/runtime/compiler"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func makeCompiler(t *testing.T) *compiler.Compiler {
diff --git a/internal/runtime/compiler/errors/BUILD.bazel b/internal/runtime/compiler/errors/BUILD.bazel
new file mode 100644
index 000000000..7ee65bbee
--- /dev/null
+++ b/internal/runtime/compiler/errors/BUILD.bazel
@@ -0,0 +1,19 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "errors",
+ srcs = ["errors.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/errors",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/runtime/compiler/position",
+ "@com_github_pkg_errors//:errors",
+ ],
+)
+
+go_test(
+ name = "errors_test",
+ size = "small",
+ srcs = ["errors_test.go"],
+ deps = [":errors"],
+)
diff --git a/internal/runtime/compiler/errors/errors.go b/internal/runtime/compiler/errors/errors.go
index 6ca97697a..446bed8e6 100644
--- a/internal/runtime/compiler/errors/errors.go
+++ b/internal/runtime/compiler/errors/errors.go
@@ -7,7 +7,7 @@ import (
"fmt"
"strings"
- "github.com/google/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
"github.com/pkg/errors"
)
@@ -20,13 +20,20 @@ func (e compileError) Error() string {
return e.pos.String() + ": " + e.msg
}
+func (e compileError) Equal(f compileError) bool {
+ if e.pos != f.pos {
+ return false
+ }
+ return e.msg == f.msg
+}
+
// ErrorList contains a list of compile errors.
type ErrorList []*compileError
// Add appends an error at a position to the list of errors.
func (p *ErrorList) Add(pos *position.Position, msg string) {
if pos == nil {
- pos = &position.Position{"", -1, -1, -1}
+ pos = &position.Position{Filename: "", Line: -1, Startcol: -1, Endcol: -1}
}
*p = append(*p, &compileError{*pos, msg})
}
@@ -37,15 +44,15 @@ func (p *ErrorList) Append(l ErrorList) {
}
// ErrorList implements the error interface.
-func (p ErrorList) Error() string {
- switch len(p) {
+func (p *ErrorList) Error() string {
+ switch len(*p) {
case 0:
return "no errors"
case 1:
- return p[0].Error()
+ return (*p)[0].Error()
}
var r strings.Builder
- for _, e := range p {
+ for _, e := range *p {
r.WriteString(fmt.Sprintf("%s\n", e))
}
return r.String()[:r.Len()-1]
diff --git a/internal/runtime/compiler/errors/errors_test.go b/internal/runtime/compiler/errors/errors_test.go
index e6018cfc8..cdf1edeac 100644
--- a/internal/runtime/compiler/errors/errors_test.go
+++ b/internal/runtime/compiler/errors/errors_test.go
@@ -6,7 +6,7 @@ package errors_test
import (
"testing"
- "github.com/google/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
)
func TestNilErrorPosition(t *testing.T) {
diff --git a/internal/runtime/compiler/opt/BUILD.bazel b/internal/runtime/compiler/opt/BUILD.bazel
new file mode 100644
index 000000000..b1a084042
--- /dev/null
+++ b/internal/runtime/compiler/opt/BUILD.bazel
@@ -0,0 +1,28 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "opt",
+ srcs = ["opt.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/opt",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/errors",
+ "//internal/runtime/compiler/parser",
+ "//internal/runtime/compiler/position",
+ "//internal/runtime/compiler/types",
+ ],
+)
+
+go_test(
+ name = "opt_test",
+ size = "small",
+ srcs = ["opt_test.go"],
+ deps = [
+ ":opt",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/parser",
+ "//internal/testutil",
+ "@com_github_google_go_cmp//cmp",
+ ],
+)
diff --git a/internal/runtime/compiler/opt/opt.go b/internal/runtime/compiler/opt/opt.go
index ab599bcdb..8946a9fab 100644
--- a/internal/runtime/compiler/opt/opt.go
+++ b/internal/runtime/compiler/opt/opt.go
@@ -7,18 +7,18 @@ package opt
import (
"math"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/errors"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/runtime/compiler/types"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
)
func Optimise(n ast.Node) (ast.Node, error) {
o := &optimiser{}
r := ast.Walk(o, n)
if len(o.errors) > 0 {
- return r, o.errors
+ return r, &o.errors
}
return r, nil
}
diff --git a/internal/runtime/compiler/opt/opt_test.go b/internal/runtime/compiler/opt/opt_test.go
index 7c8227947..2b1e58479 100644
--- a/internal/runtime/compiler/opt/opt_test.go
+++ b/internal/runtime/compiler/opt/opt_test.go
@@ -12,10 +12,10 @@ import (
"testing/quick"
"github.com/google/go-cmp/cmp"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/opt"
- "github.com/google/mtail/internal/runtime/compiler/parser"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/opt"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/parser"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var optimiserTests = []struct {
diff --git a/internal/runtime/compiler/parser/BUILD.bazel b/internal/runtime/compiler/parser/BUILD.bazel
new file mode 100644
index 000000000..f32de7704
--- /dev/null
+++ b/internal/runtime/compiler/parser/BUILD.bazel
@@ -0,0 +1,47 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+load("//build:goyacc.bzl", "go_yacc")
+
+go_yacc(
+ name = "parser_go_gen",
+ src = "parser.y",
+ out = "parser.go",
+ prefix = "mtail",
+)
+
+go_library(
+ name = "parser",
+ srcs = [
+ "driver.go",
+ "lexer.go",
+ "parser.go", # keep
+ "sexp.go",
+ "tokens.go",
+ "unparser.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/parser",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/metrics",
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/errors",
+ "//internal/runtime/compiler/position",
+ "//internal/runtime/compiler/symbol",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "parser_test",
+ size = "small",
+ srcs = [
+ "lexer_test.go",
+ "parser_test.go",
+ "tokens_test.go",
+ ],
+ embed = [":parser"],
+ deps = [
+ "//internal/runtime/compiler/ast",
+ "//internal/runtime/compiler/position",
+ "//internal/testutil",
+ ],
+)
diff --git a/internal/runtime/compiler/parser/driver.go b/internal/runtime/compiler/parser/driver.go
index 1adbb5c50..af5aabf6e 100644
--- a/internal/runtime/compiler/parser/driver.go
+++ b/internal/runtime/compiler/parser/driver.go
@@ -24,9 +24,9 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/errors"
- "github.com/google/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
)
// Parse reads the program named name from the input, and if successful returns
@@ -35,7 +35,7 @@ func Parse(name string, input io.Reader) (ast.Node, error) {
p := newParser(name, input)
r := mtailParse(p)
if r != 0 || p.errors != nil {
- return nil, p.errors
+ return nil, &p.errors
}
return p.root, nil
}
diff --git a/internal/runtime/compiler/parser/lexer.go b/internal/runtime/compiler/parser/lexer.go
index 98879e7a8..94e86ad4e 100644
--- a/internal/runtime/compiler/parser/lexer.go
+++ b/internal/runtime/compiler/parser/lexer.go
@@ -13,34 +13,36 @@ import (
"unicode"
"github.com/golang/glog"
- "github.com/google/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
)
// List of keywords. Keep this list sorted!
var keywords = map[string]Kind{
- "after": AFTER,
- "as": AS,
- "buckets": BUCKETS,
- "by": BY,
- "const": CONST,
- "counter": COUNTER,
- "def": DEF,
- "del": DEL,
- "else": ELSE,
- "gauge": GAUGE,
- "hidden": HIDDEN,
- "histogram": HISTOGRAM,
- "limit": LIMIT,
- "next": NEXT,
- "otherwise": OTHERWISE,
- "stop": STOP,
- "text": TEXT,
- "timer": TIMER,
+ "after": AFTER,
+ "as": AS,
+ "buckets": BUCKETS,
+ "by": BY,
+ "const": CONST,
+ "counter": COUNTER,
+ "def": DEF,
+ "del": DEL,
+ "else": ELSE,
+ "gauge": GAUGE,
+ "hidden": HIDDEN,
+ "histogram": HISTOGRAM,
+ "limit": LIMIT,
+ "log_filter": LOGFILTER,
+ "next": NEXT,
+ "otherwise": OTHERWISE,
+ "stop": STOP,
+ "text": TEXT,
+ "timer": TIMER,
}
// List of builtin functions. Keep this list sorted!
var builtins = []string{
"bool",
+ "defined",
"float",
"getfilename",
"int",
diff --git a/internal/runtime/compiler/parser/lexer_test.go b/internal/runtime/compiler/parser/lexer_test.go
index a8e4d497f..cdd82e2f5 100644
--- a/internal/runtime/compiler/parser/lexer_test.go
+++ b/internal/runtime/compiler/parser/lexer_test.go
@@ -7,8 +7,8 @@ import (
"strings"
"testing"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
type lexerTest struct {
diff --git a/internal/runtime/compiler/parser/parser.go b/internal/runtime/compiler/parser/parser.go
deleted file mode 100644
index e9c6125c9..000000000
--- a/internal/runtime/compiler/parser/parser.go
+++ /dev/null
@@ -1,1504 +0,0 @@
-// Code generated by goyacc -v y.output -o parser.go -p mtail parser.y. DO NOT EDIT.
-
-//line parser.y:5
-/* #nosec G104 generated code, errors reported do not make sense */
-package parser
-
-import __yyfmt__ "fmt"
-
-//line parser.y:6
-
-import (
- "time"
-
- "github.com/golang/glog"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/position"
-)
-
-//line parser.y:19
-type mtailSymType struct {
- yys int
- intVal int64
- floatVal float64
- floats []float64
- op int
- text string
- texts []string
- flag bool
- n ast.Node
- kind metrics.Kind
- duration time.Duration
-}
-
-const INVALID = 57346
-const COUNTER = 57347
-const GAUGE = 57348
-const TIMER = 57349
-const TEXT = 57350
-const HISTOGRAM = 57351
-const AFTER = 57352
-const AS = 57353
-const BY = 57354
-const CONST = 57355
-const HIDDEN = 57356
-const DEF = 57357
-const DEL = 57358
-const NEXT = 57359
-const OTHERWISE = 57360
-const ELSE = 57361
-const STOP = 57362
-const BUCKETS = 57363
-const LIMIT = 57364
-const BUILTIN = 57365
-const REGEX = 57366
-const STRING = 57367
-const CAPREF = 57368
-const CAPREF_NAMED = 57369
-const ID = 57370
-const DECO = 57371
-const INTLITERAL = 57372
-const FLOATLITERAL = 57373
-const DURATIONLITERAL = 57374
-const INC = 57375
-const DEC = 57376
-const DIV = 57377
-const MOD = 57378
-const MUL = 57379
-const MINUS = 57380
-const PLUS = 57381
-const POW = 57382
-const SHL = 57383
-const SHR = 57384
-const LT = 57385
-const GT = 57386
-const LE = 57387
-const GE = 57388
-const EQ = 57389
-const NE = 57390
-const BITAND = 57391
-const XOR = 57392
-const BITOR = 57393
-const NOT = 57394
-const AND = 57395
-const OR = 57396
-const ADD_ASSIGN = 57397
-const ASSIGN = 57398
-const MATCH = 57399
-const NOT_MATCH = 57400
-const LCURLY = 57401
-const RCURLY = 57402
-const LPAREN = 57403
-const RPAREN = 57404
-const LSQUARE = 57405
-const RSQUARE = 57406
-const COMMA = 57407
-const NL = 57408
-
-var mtailToknames = [...]string{
- "$end",
- "error",
- "$unk",
- "INVALID",
- "COUNTER",
- "GAUGE",
- "TIMER",
- "TEXT",
- "HISTOGRAM",
- "AFTER",
- "AS",
- "BY",
- "CONST",
- "HIDDEN",
- "DEF",
- "DEL",
- "NEXT",
- "OTHERWISE",
- "ELSE",
- "STOP",
- "BUCKETS",
- "LIMIT",
- "BUILTIN",
- "REGEX",
- "STRING",
- "CAPREF",
- "CAPREF_NAMED",
- "ID",
- "DECO",
- "INTLITERAL",
- "FLOATLITERAL",
- "DURATIONLITERAL",
- "INC",
- "DEC",
- "DIV",
- "MOD",
- "MUL",
- "MINUS",
- "PLUS",
- "POW",
- "SHL",
- "SHR",
- "LT",
- "GT",
- "LE",
- "GE",
- "EQ",
- "NE",
- "BITAND",
- "XOR",
- "BITOR",
- "NOT",
- "AND",
- "OR",
- "ADD_ASSIGN",
- "ASSIGN",
- "MATCH",
- "NOT_MATCH",
- "LCURLY",
- "RCURLY",
- "LPAREN",
- "RPAREN",
- "LSQUARE",
- "RSQUARE",
- "COMMA",
- "NL",
-}
-
-var mtailStatenames = [...]string{}
-
-const mtailEofCode = 1
-const mtailErrCode = 2
-const mtailInitialStackSize = 16
-
-//line parser.y:733
-
-// tokenpos returns the position of the current token.
-func tokenpos(mtaillex mtailLexer) position.Position {
- return mtaillex.(*parser).t.Pos
-}
-
-// markedpos returns the position recorded from the most recent mark_pos
-// production.
-func markedpos(mtaillex mtailLexer) position.Position {
- return mtaillex.(*parser).pos
-}
-
-// positionFromMark returns a position spanning from the last mark to the current position.
-func positionFromMark(mtaillex mtailLexer) position.Position {
- tp := tokenpos(mtaillex)
- mp := markedpos(mtaillex)
- return *position.Merge(&mp, &tp)
-}
-
-//line yacctab:1
-var mtailExca = [...]int{
- -1, 1,
- 1, -1,
- -2, 0,
- -1, 2,
- 1, 1,
- 5, 93,
- 6, 93,
- 7, 93,
- 8, 93,
- 9, 93,
- -2, 124,
- -1, 22,
- 66, 24,
- -2, 68,
- -1, 106,
- 5, 93,
- 6, 93,
- 7, 93,
- 8, 93,
- 9, 93,
- -2, 124,
-}
-
-const mtailPrivate = 57344
-
-const mtailLast = 249
-
-var mtailAct = [...]int{
- 171, 88, 126, 28, 15, 91, 42, 44, 27, 30,
- 103, 127, 41, 24, 20, 86, 40, 167, 22, 128,
- 163, 182, 19, 26, 45, 29, 104, 25, 36, 34,
- 35, 43, 54, 38, 39, 87, 181, 85, 89, 125,
- 108, 46, 36, 34, 35, 43, 47, 38, 39, 90,
- 162, 163, 62, 63, 2, 31, 49, 87, 76, 77,
- 68, 130, 74, 73, 37, 138, 62, 63, 50, 112,
- 93, 94, 117, 97, 96, 118, 168, 50, 37, 119,
- 120, 70, 72, 71, 121, 122, 123, 66, 67, 124,
- 107, 129, 185, 184, 111, 79, 80, 81, 82, 83,
- 84, 169, 106, 131, 179, 135, 132, 175, 15, 133,
- 129, 43, 27, 110, 100, 101, 99, 134, 20, 102,
- 174, 135, 22, 173, 87, 129, 19, 160, 87, 151,
- 156, 142, 155, 157, 158, 87, 87, 87, 164, 166,
- 165, 161, 153, 159, 140, 154, 152, 136, 139, 178,
- 177, 13, 141, 116, 66, 67, 115, 49, 105, 109,
- 11, 23, 1, 176, 10, 129, 180, 12, 64, 145,
- 13, 65, 36, 34, 35, 43, 75, 38, 39, 11,
- 23, 98, 183, 10, 95, 69, 12, 92, 61, 78,
- 18, 36, 34, 35, 43, 170, 38, 39, 143, 31,
- 56, 57, 58, 59, 60, 172, 144, 137, 37, 36,
- 34, 35, 43, 16, 38, 39, 146, 55, 31, 33,
- 51, 53, 114, 48, 9, 8, 7, 37, 49, 113,
- 6, 32, 16, 21, 52, 17, 31, 148, 147, 5,
- 50, 14, 4, 3, 0, 37, 0, 149, 150,
-}
-
-var mtailPact = [...]int{
- -1000, -1000, 166, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
- -1000, 83, -1000, -1000, -13, 205, -1000, -34, 195, 13,
- 13, -1000, 54, -1000, 21, 32, -1000, 7, 1, -1000,
- 52, 184, -25, -1000, -1000, -1000, -1000, 184, -1000, -1000,
- 29, -1000, 35, -1000, 79, -40, 139, -1000, -13, -21,
- -1000, 85, -13, 17, -1000, 128, -1000, -1000, -1000, -1000,
- -1000, -40, -1000, -1000, -40, -1000, -1000, -1000, -40, -40,
- -1000, -1000, -1000, -40, -40, -40, -1000, -1000, -40, -1000,
- -1000, -1000, -1000, -1000, -1000, -1000, 54, -1000, 134, 184,
- -1, -1000, -40, -1000, -1000, -40, -1000, -1000, -40, -1000,
- -1000, -1000, -1000, -1000, -1000, -13, 147, -1000, 3, 120,
- -13, -1000, 121, 226, -1000, -1000, -1000, 184, 184, 83,
- 184, 184, 184, 17, 184, -14, -1000, 13, -1000, 33,
- -1000, 184, 184, 184, 21, 42, -1000, -1000, -1000, -45,
- 41, -1000, 69, -1000, -1000, -1000, -1000, 95, 82, 119,
- 74, 13, 32, -1000, -1000, -1000, 52, 13, 13, -1000,
- -1000, 29, -1000, 184, 35, 79, -1000, -1000, -1000, -1000,
- -29, -1000, -1000, -1000, -1000, -1000, -44, -1000, -1000, -1000,
- -1000, 95, 62, -1000, -1000, -1000,
-}
-
-var mtailPgo = [...]int{
- 0, 54, 243, 39, 41, 242, 241, 239, 235, 3,
- 7, 6, 15, 5, 233, 9, 16, 27, 11, 231,
- 12, 13, 19, 230, 229, 226, 225, 25, 23, 224,
- 222, 219, 2, 217, 216, 206, 205, 0, 198, 195,
- 190, 189, 187, 185, 168, 184, 181, 176, 171, 169,
- 163, 162, 10, 1, 159,
-}
-
-var mtailR1 = [...]int{
- 0, 51, 1, 1, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 5, 5, 5, 6, 6, 6,
- 7, 7, 4, 8, 8, 14, 14, 18, 18, 18,
- 18, 44, 44, 17, 17, 43, 43, 43, 15, 15,
- 41, 41, 41, 41, 41, 41, 16, 16, 42, 42,
- 11, 11, 45, 45, 28, 28, 47, 47, 22, 21,
- 21, 21, 10, 10, 46, 46, 46, 46, 13, 13,
- 12, 12, 48, 48, 9, 9, 9, 9, 9, 9,
- 9, 9, 19, 19, 20, 31, 31, 3, 3, 32,
- 32, 27, 23, 40, 40, 24, 24, 24, 24, 24,
- 30, 30, 33, 33, 33, 33, 33, 38, 39, 39,
- 37, 35, 34, 49, 50, 50, 50, 50, 25, 26,
- 29, 29, 36, 36, 53, 54, 52, 52,
-}
-
-var mtailR2 = [...]int{
- 0, 1, 0, 2, 1, 1, 1, 1, 1, 1,
- 1, 4, 1, 1, 4, 2, 3, 1, 4, 1,
- 1, 2, 3, 1, 1, 4, 4, 1, 1, 4,
- 4, 1, 1, 1, 4, 1, 1, 1, 1, 4,
- 1, 1, 1, 1, 1, 1, 1, 4, 1, 1,
- 1, 4, 1, 1, 4, 4, 1, 1, 1, 1,
- 4, 4, 1, 4, 1, 1, 1, 1, 1, 2,
- 1, 2, 1, 1, 1, 1, 1, 1, 1, 3,
- 1, 1, 1, 4, 1, 4, 5, 1, 3, 1,
- 1, 5, 3, 0, 1, 2, 2, 2, 2, 1,
- 1, 1, 1, 1, 1, 1, 1, 2, 1, 3,
- 1, 2, 2, 2, 1, 1, 3, 3, 4, 3,
- 5, 3, 1, 1, 0, 0, 0, 1,
-}
-
-var mtailChk = [...]int{
- -1000, -51, -1, -2, -5, -7, -23, -25, -26, -29,
- 17, 13, 20, 4, -6, -53, 66, -8, -40, -22,
- -18, -14, -12, 14, -21, -17, -28, -13, -9, -27,
- -15, 52, -19, -31, 26, 27, 25, 61, 30, 31,
- -16, -20, -11, 28, -10, -20, -4, 59, 18, 23,
- 35, 15, 29, 16, 66, -33, 5, 6, 7, 8,
- 9, -44, 53, 54, -44, -48, 33, 34, 39, -43,
- 49, 51, 50, 56, 55, -47, 57, 58, -41, 43,
- 44, 45, 46, 47, 48, -13, -12, -9, -53, 63,
- -18, -13, -42, 41, 42, -45, 39, 38, -46, 37,
- 35, 36, 40, -52, 66, 19, -1, -4, 61, -54,
- 28, -4, -12, -24, -30, 28, 25, -52, -52, -52,
- -52, -52, -52, -52, -52, -3, -32, -18, -22, -53,
- 62, -52, -52, -52, -21, -53, -4, 60, 62, -3,
- 24, -4, 10, -38, -35, -49, -34, 12, 11, 21,
- 22, -18, -17, -28, -27, -20, -15, -18, -18, -22,
- -9, -16, 64, 65, -11, -10, -13, 62, 35, 32,
- -39, -37, -36, 28, 25, 25, -50, 31, 30, 30,
- -32, 65, 65, -37, 31, 30,
-}
-
-var mtailDef = [...]int{
- 2, -2, -2, 3, 4, 5, 6, 7, 8, 9,
- 10, 0, 12, 13, 0, 0, 20, 0, 0, 17,
- 19, 23, -2, 94, 58, 27, 28, 62, 70, 59,
- 33, 124, 74, 75, 76, 77, 78, 124, 80, 81,
- 38, 82, 46, 84, 50, 126, 15, 2, 0, 0,
- 125, 0, 0, 124, 21, 0, 102, 103, 104, 105,
- 106, 126, 31, 32, 126, 71, 72, 73, 126, 126,
- 35, 36, 37, 126, 126, 126, 56, 57, 126, 40,
- 41, 42, 43, 44, 45, 69, 68, 70, 0, 124,
- 0, 62, 126, 48, 49, 126, 52, 53, 126, 64,
- 65, 66, 67, 124, 127, 0, -2, 16, 124, 0,
- 0, 119, 121, 92, 99, 100, 101, 124, 124, 124,
- 124, 124, 124, 124, 124, 0, 87, 89, 90, 0,
- 79, 124, 124, 124, 11, 0, 14, 22, 85, 0,
- 0, 118, 0, 95, 96, 97, 98, 0, 0, 0,
- 0, 18, 29, 30, 60, 61, 34, 25, 26, 54,
- 55, 39, 83, 124, 47, 51, 63, 86, 91, 120,
- 107, 108, 110, 122, 123, 111, 113, 114, 115, 112,
- 88, 0, 0, 109, 116, 117,
-}
-
-var mtailTok1 = [...]int{
- 1,
-}
-
-var mtailTok2 = [...]int{
- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
- 62, 63, 64, 65, 66,
-}
-
-var mtailTok3 = [...]int{
- 0,
-}
-
-var mtailErrorMessages = [...]struct {
- state int
- token int
- msg string
-}{
- {109, 4, "unexpected end of file, expecting '/' to end regex"},
- {15, 1, "unexpected end of file, expecting '}' to end block"},
- {15, 1, "unexpected end of file, expecting '}' to end block"},
- {15, 1, "unexpected end of file, expecting '}' to end block"},
- {14, 63, "unexpected indexing of an expression"},
- {14, 66, "statement with no effect, missing an assignment, `+' concatenation, or `{}' block?"},
-}
-
-//line yaccpar:1
-
-/* parser for yacc output */
-
-var (
- mtailDebug = 0
- mtailErrorVerbose = false
-)
-
-type mtailLexer interface {
- Lex(lval *mtailSymType) int
- Error(s string)
-}
-
-type mtailParser interface {
- Parse(mtailLexer) int
- Lookahead() int
-}
-
-type mtailParserImpl struct {
- lval mtailSymType
- stack [mtailInitialStackSize]mtailSymType
- char int
-}
-
-func (p *mtailParserImpl) Lookahead() int {
- return p.char
-}
-
-func mtailNewParser() mtailParser {
- return &mtailParserImpl{}
-}
-
-const mtailFlag = -1000
-
-func mtailTokname(c int) string {
- if c >= 1 && c-1 < len(mtailToknames) {
- if mtailToknames[c-1] != "" {
- return mtailToknames[c-1]
- }
- }
- return __yyfmt__.Sprintf("tok-%v", c)
-}
-
-func mtailStatname(s int) string {
- if s >= 0 && s < len(mtailStatenames) {
- if mtailStatenames[s] != "" {
- return mtailStatenames[s]
- }
- }
- return __yyfmt__.Sprintf("state-%v", s)
-}
-
-func mtailErrorMessage(state, lookAhead int) string {
- const TOKSTART = 4
-
- if !mtailErrorVerbose {
- return "syntax error"
- }
-
- for _, e := range mtailErrorMessages {
- if e.state == state && e.token == lookAhead {
- return "syntax error: " + e.msg
- }
- }
-
- res := "syntax error: unexpected " + mtailTokname(lookAhead)
-
- // To match Bison, suggest at most four expected tokens.
- expected := make([]int, 0, 4)
-
- // Look for shiftable tokens.
- base := mtailPact[state]
- for tok := TOKSTART; tok-1 < len(mtailToknames); tok++ {
- if n := base + tok; n >= 0 && n < mtailLast && mtailChk[mtailAct[n]] == tok {
- if len(expected) == cap(expected) {
- return res
- }
- expected = append(expected, tok)
- }
- }
-
- if mtailDef[state] == -2 {
- i := 0
- for mtailExca[i] != -1 || mtailExca[i+1] != state {
- i += 2
- }
-
- // Look for tokens that we accept or reduce.
- for i += 2; mtailExca[i] >= 0; i += 2 {
- tok := mtailExca[i]
- if tok < TOKSTART || mtailExca[i+1] == 0 {
- continue
- }
- if len(expected) == cap(expected) {
- return res
- }
- expected = append(expected, tok)
- }
-
- // If the default action is to accept or reduce, give up.
- if mtailExca[i+1] != 0 {
- return res
- }
- }
-
- for i, tok := range expected {
- if i == 0 {
- res += ", expecting "
- } else {
- res += " or "
- }
- res += mtailTokname(tok)
- }
- return res
-}
-
-func mtaillex1(lex mtailLexer, lval *mtailSymType) (char, token int) {
- token = 0
- char = lex.Lex(lval)
- if char <= 0 {
- token = mtailTok1[0]
- goto out
- }
- if char < len(mtailTok1) {
- token = mtailTok1[char]
- goto out
- }
- if char >= mtailPrivate {
- if char < mtailPrivate+len(mtailTok2) {
- token = mtailTok2[char-mtailPrivate]
- goto out
- }
- }
- for i := 0; i < len(mtailTok3); i += 2 {
- token = mtailTok3[i+0]
- if token == char {
- token = mtailTok3[i+1]
- goto out
- }
- }
-
-out:
- if token == 0 {
- token = mtailTok2[1] /* unknown char */
- }
- if mtailDebug >= 3 {
- __yyfmt__.Printf("lex %s(%d)\n", mtailTokname(token), uint(char))
- }
- return char, token
-}
-
-func mtailParse(mtaillex mtailLexer) int {
- return mtailNewParser().Parse(mtaillex)
-}
-
-func (mtailrcvr *mtailParserImpl) Parse(mtaillex mtailLexer) int {
- var mtailn int
- var mtailVAL mtailSymType
- var mtailDollar []mtailSymType
- _ = mtailDollar // silence set and not used
- mtailS := mtailrcvr.stack[:]
-
- Nerrs := 0 /* number of errors */
- Errflag := 0 /* error recovery flag */
- mtailstate := 0
- mtailrcvr.char = -1
- mtailtoken := -1 // mtailrcvr.char translated into internal numbering
- defer func() {
- // Make sure we report no lookahead when not parsing.
- mtailstate = -1
- mtailrcvr.char = -1
- mtailtoken = -1
- }()
- mtailp := -1
- goto mtailstack
-
-ret0:
- return 0
-
-ret1:
- return 1
-
-mtailstack:
- /* put a state and value onto the stack */
- if mtailDebug >= 4 {
- __yyfmt__.Printf("char %v in %v\n", mtailTokname(mtailtoken), mtailStatname(mtailstate))
- }
-
- mtailp++
- if mtailp >= len(mtailS) {
- nyys := make([]mtailSymType, len(mtailS)*2)
- copy(nyys, mtailS)
- mtailS = nyys
- }
- mtailS[mtailp] = mtailVAL
- mtailS[mtailp].yys = mtailstate
-
-mtailnewstate:
- mtailn = mtailPact[mtailstate]
- if mtailn <= mtailFlag {
- goto mtaildefault /* simple state */
- }
- if mtailrcvr.char < 0 {
- mtailrcvr.char, mtailtoken = mtaillex1(mtaillex, &mtailrcvr.lval)
- }
- mtailn += mtailtoken
- if mtailn < 0 || mtailn >= mtailLast {
- goto mtaildefault
- }
- mtailn = mtailAct[mtailn]
- if mtailChk[mtailn] == mtailtoken { /* valid shift */
- mtailrcvr.char = -1
- mtailtoken = -1
- mtailVAL = mtailrcvr.lval
- mtailstate = mtailn
- if Errflag > 0 {
- Errflag--
- }
- goto mtailstack
- }
-
-mtaildefault:
- /* default state action */
- mtailn = mtailDef[mtailstate]
- if mtailn == -2 {
- if mtailrcvr.char < 0 {
- mtailrcvr.char, mtailtoken = mtaillex1(mtaillex, &mtailrcvr.lval)
- }
-
- /* look through exception table */
- xi := 0
- for {
- if mtailExca[xi+0] == -1 && mtailExca[xi+1] == mtailstate {
- break
- }
- xi += 2
- }
- for xi += 2; ; xi += 2 {
- mtailn = mtailExca[xi+0]
- if mtailn < 0 || mtailn == mtailtoken {
- break
- }
- }
- mtailn = mtailExca[xi+1]
- if mtailn < 0 {
- goto ret0
- }
- }
- if mtailn == 0 {
- /* error ... attempt to resume parsing */
- switch Errflag {
- case 0: /* brand new error */
- mtaillex.Error(mtailErrorMessage(mtailstate, mtailtoken))
- Nerrs++
- if mtailDebug >= 1 {
- __yyfmt__.Printf("%s", mtailStatname(mtailstate))
- __yyfmt__.Printf(" saw %s\n", mtailTokname(mtailtoken))
- }
- fallthrough
-
- case 1, 2: /* incompletely recovered error ... try again */
- Errflag = 3
-
- /* find a state where "error" is a legal shift action */
- for mtailp >= 0 {
- mtailn = mtailPact[mtailS[mtailp].yys] + mtailErrCode
- if mtailn >= 0 && mtailn < mtailLast {
- mtailstate = mtailAct[mtailn] /* simulate a shift of "error" */
- if mtailChk[mtailstate] == mtailErrCode {
- goto mtailstack
- }
- }
-
- /* the current p has no shift on "error", pop stack */
- if mtailDebug >= 2 {
- __yyfmt__.Printf("error recovery pops state %d\n", mtailS[mtailp].yys)
- }
- mtailp--
- }
- /* there is no state on the stack with an error shift ... abort */
- goto ret1
-
- case 3: /* no shift yet; clobber input char */
- if mtailDebug >= 2 {
- __yyfmt__.Printf("error recovery discards %s\n", mtailTokname(mtailtoken))
- }
- if mtailtoken == mtailEofCode {
- goto ret1
- }
- mtailrcvr.char = -1
- mtailtoken = -1
- goto mtailnewstate /* try again in the same state */
- }
- }
-
- /* reduction by production mtailn */
- if mtailDebug >= 2 {
- __yyfmt__.Printf("reduce %v in:\n\t%v\n", mtailn, mtailStatname(mtailstate))
- }
-
- mtailnt := mtailn
- mtailpt := mtailp
- _ = mtailpt // guard against "declared and not used"
-
- mtailp -= mtailR2[mtailn]
- // mtailp is now the index of $0. Perform the default action. Iff the
- // reduced production is Ξ΅, $1 is possibly out of range.
- if mtailp+1 >= len(mtailS) {
- nyys := make([]mtailSymType, len(mtailS)*2)
- copy(nyys, mtailS)
- mtailS = nyys
- }
- mtailVAL = mtailS[mtailp+1]
-
- /* consult goto table to find next state */
- mtailn = mtailR1[mtailn]
- mtailg := mtailPgo[mtailn]
- mtailj := mtailg + mtailS[mtailp].yys + 1
-
- if mtailj >= mtailLast {
- mtailstate = mtailAct[mtailg]
- } else {
- mtailstate = mtailAct[mtailj]
- if mtailChk[mtailstate] != -mtailn {
- mtailstate = mtailAct[mtailg]
- }
- }
- // dummy call; replaced with literal code
- switch mtailnt {
-
- case 1:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:93
- {
- mtaillex.(*parser).root = mtailDollar[1].n
- }
- case 2:
- mtailDollar = mtailS[mtailpt-0 : mtailpt+1]
-//line parser.y:101
- {
- mtailVAL.n = &ast.StmtList{}
- }
- case 3:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:105
- {
- mtailVAL.n = mtailDollar[1].n
- if mtailDollar[2].n != nil {
- mtailVAL.n.(*ast.StmtList).Children = append(mtailVAL.n.(*ast.StmtList).Children, mtailDollar[2].n)
- }
- }
- case 4:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:116
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 5:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:118
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 6:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:120
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 7:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:122
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 8:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:124
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 9:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:126
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 10:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:128
- {
- mtailVAL.n = &ast.NextStmt{tokenpos(mtaillex)}
- }
- case 11:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:132
- {
- mtailVAL.n = &ast.PatternFragment{ID: mtailDollar[2].n, Expr: mtailDollar[4].n}
- }
- case 12:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:136
- {
- mtailVAL.n = &ast.StopStmt{tokenpos(mtaillex)}
- }
- case 13:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:140
- {
- mtailVAL.n = &ast.Error{tokenpos(mtaillex), mtailDollar[1].text}
- }
- case 14:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:148
- {
- mtailVAL.n = &ast.CondStmt{mtailDollar[1].n, mtailDollar[2].n, mtailDollar[4].n, nil}
- }
- case 15:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:152
- {
- if mtailDollar[1].n != nil {
- mtailVAL.n = &ast.CondStmt{mtailDollar[1].n, mtailDollar[2].n, nil, nil}
- } else {
- mtailVAL.n = mtailDollar[2].n
- }
- }
- case 16:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:160
- {
- o := &ast.OtherwiseStmt{positionFromMark(mtaillex)}
- mtailVAL.n = &ast.CondStmt{o, mtailDollar[3].n, nil, nil}
- }
- case 17:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:168
- {
- mtailVAL.n = &ast.UnaryExpr{P: tokenpos(mtaillex), Expr: mtailDollar[1].n, Op: MATCH}
- }
- case 18:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:172
- {
- mtailVAL.n = &ast.BinaryExpr{
- LHS: &ast.UnaryExpr{P: tokenpos(mtaillex), Expr: mtailDollar[1].n, Op: MATCH},
- RHS: mtailDollar[4].n,
- Op: mtailDollar[2].op,
- }
- }
- case 19:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:180
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 20:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:186
- {
- mtailVAL.n = nil
- }
- case 21:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:188
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 22:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:194
- {
- mtailVAL.n = mtailDollar[2].n
- }
- case 23:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:202
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 24:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:204
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 25:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:210
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 26:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:214
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 27:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:222
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 28:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:224
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 29:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:226
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 30:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:230
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 31:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:237
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 32:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:239
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 33:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:245
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 34:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:247
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 35:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:254
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 36:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:256
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 37:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:258
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 38:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:264
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 39:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:266
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 40:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:273
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 41:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:275
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 42:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:277
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 43:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:279
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 44:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:281
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 45:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:283
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 46:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:289
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 47:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:291
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 48:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:298
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 49:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:300
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 50:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:306
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 51:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:308
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 52:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:315
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 53:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:317
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 54:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:323
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 55:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:327
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 56:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:334
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 57:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:336
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 58:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:343
- {
- mtailVAL.n = &ast.PatternExpr{Expr: mtailDollar[1].n}
- }
- case 59:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:351
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 60:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:353
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: PLUS}
- }
- case 61:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:357
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: PLUS}
- }
- case 62:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:365
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 63:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:367
- {
- mtailVAL.n = &ast.BinaryExpr{LHS: mtailDollar[1].n, RHS: mtailDollar[4].n, Op: mtailDollar[2].op}
- }
- case 64:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:374
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 65:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:376
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 66:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:378
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 67:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:380
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 68:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:386
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 69:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:388
- {
- mtailVAL.n = &ast.UnaryExpr{P: tokenpos(mtaillex), Expr: mtailDollar[2].n, Op: mtailDollar[1].op}
- }
- case 70:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:396
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 71:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:398
- {
- mtailVAL.n = &ast.UnaryExpr{P: tokenpos(mtaillex), Expr: mtailDollar[1].n, Op: mtailDollar[2].op}
- }
- case 72:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:405
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 73:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:407
- {
- mtailVAL.op = mtailDollar[1].op
- }
- case 74:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:413
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 75:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:415
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 76:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:417
- {
- mtailVAL.n = &ast.CaprefTerm{tokenpos(mtaillex), mtailDollar[1].text, false, nil}
- }
- case 77:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:421
- {
- mtailVAL.n = &ast.CaprefTerm{tokenpos(mtaillex), mtailDollar[1].text, true, nil}
- }
- case 78:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:425
- {
- mtailVAL.n = &ast.StringLit{tokenpos(mtaillex), mtailDollar[1].text}
- }
- case 79:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:429
- {
- mtailVAL.n = mtailDollar[2].n
- }
- case 80:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:433
- {
- mtailVAL.n = &ast.IntLit{tokenpos(mtaillex), mtailDollar[1].intVal}
- }
- case 81:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:437
- {
- mtailVAL.n = &ast.FloatLit{tokenpos(mtaillex), mtailDollar[1].floatVal}
- }
- case 82:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:445
- {
- // Build an empty IndexedExpr so that the recursive rule below doesn't need to handle the alternative.
- mtailVAL.n = &ast.IndexedExpr{LHS: mtailDollar[1].n, Index: &ast.ExprList{}}
- }
- case 83:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:450
- {
- mtailVAL.n = mtailDollar[1].n
- mtailVAL.n.(*ast.IndexedExpr).Index.(*ast.ExprList).Children = append(
- mtailVAL.n.(*ast.IndexedExpr).Index.(*ast.ExprList).Children,
- mtailDollar[3].n.(*ast.ExprList).Children...)
- }
- case 84:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:461
- {
- mtailVAL.n = &ast.IDTerm{tokenpos(mtaillex), mtailDollar[1].text, nil, false}
- }
- case 85:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:469
- {
- mtailVAL.n = &ast.BuiltinExpr{P: positionFromMark(mtaillex), Name: mtailDollar[2].text, Args: nil}
- }
- case 86:
- mtailDollar = mtailS[mtailpt-5 : mtailpt+1]
-//line parser.y:473
- {
- mtailVAL.n = &ast.BuiltinExpr{P: positionFromMark(mtaillex), Name: mtailDollar[2].text, Args: mtailDollar[4].n}
- }
- case 87:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:482
- {
- mtailVAL.n = &ast.ExprList{}
- mtailVAL.n.(*ast.ExprList).Children = append(mtailVAL.n.(*ast.ExprList).Children, mtailDollar[1].n)
- }
- case 88:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:487
- {
- mtailVAL.n = mtailDollar[1].n
- mtailVAL.n.(*ast.ExprList).Children = append(mtailVAL.n.(*ast.ExprList).Children, mtailDollar[3].n)
- }
- case 89:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:495
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 90:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:497
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 91:
- mtailDollar = mtailS[mtailpt-5 : mtailpt+1]
-//line parser.y:503
- {
- mtailVAL.n = &ast.PatternLit{P: positionFromMark(mtaillex), Pattern: mtailDollar[4].text}
- }
- case 92:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:511
- {
- mtailVAL.n = mtailDollar[3].n
- d := mtailVAL.n.(*ast.VarDecl)
- d.Kind = mtailDollar[2].kind
- d.Hidden = mtailDollar[1].flag
- }
- case 93:
- mtailDollar = mtailS[mtailpt-0 : mtailpt+1]
-//line parser.y:522
- {
- mtailVAL.flag = false
- }
- case 94:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:526
- {
- mtailVAL.flag = true
- }
- case 95:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:534
- {
- mtailVAL.n = mtailDollar[1].n
- mtailVAL.n.(*ast.VarDecl).Keys = mtailDollar[2].texts
- }
- case 96:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:539
- {
- mtailVAL.n = mtailDollar[1].n
- mtailVAL.n.(*ast.VarDecl).ExportedName = mtailDollar[2].text
- }
- case 97:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:544
- {
- mtailVAL.n = mtailDollar[1].n
- mtailVAL.n.(*ast.VarDecl).Buckets = mtailDollar[2].floats
- }
- case 98:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:549
- {
- mtailVAL.n = mtailDollar[1].n
- mtailVAL.n.(*ast.VarDecl).Limit = mtailDollar[2].intVal
- }
- case 99:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:554
- {
- mtailVAL.n = mtailDollar[1].n
- }
- case 100:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:562
- {
- mtailVAL.n = &ast.VarDecl{P: tokenpos(mtaillex), Name: mtailDollar[1].text}
- }
- case 101:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:566
- {
- mtailVAL.n = &ast.VarDecl{P: tokenpos(mtaillex), Name: mtailDollar[1].text}
- }
- case 102:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:574
- {
- mtailVAL.kind = metrics.Counter
- }
- case 103:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:578
- {
- mtailVAL.kind = metrics.Gauge
- }
- case 104:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:582
- {
- mtailVAL.kind = metrics.Timer
- }
- case 105:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:586
- {
- mtailVAL.kind = metrics.Text
- }
- case 106:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:590
- {
- mtailVAL.kind = metrics.Histogram
- }
- case 107:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:598
- {
- mtailVAL.texts = mtailDollar[2].texts
- }
- case 108:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:605
- {
- mtailVAL.texts = make([]string, 0)
- mtailVAL.texts = append(mtailVAL.texts, mtailDollar[1].text)
- }
- case 109:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:610
- {
- mtailVAL.texts = mtailDollar[1].texts
- mtailVAL.texts = append(mtailVAL.texts, mtailDollar[3].text)
- }
- case 110:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:618
- {
- mtailVAL.text = mtailDollar[1].text
- }
- case 111:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:624
- {
- mtailVAL.text = mtailDollar[2].text
- }
- case 112:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:631
- {
- mtailVAL.intVal = mtailDollar[2].intVal
- }
- case 113:
- mtailDollar = mtailS[mtailpt-2 : mtailpt+1]
-//line parser.y:639
- {
- mtailVAL.floats = mtailDollar[2].floats
- }
- case 114:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:645
- {
- mtailVAL.floats = make([]float64, 0)
- mtailVAL.floats = append(mtailVAL.floats, mtailDollar[1].floatVal)
- }
- case 115:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:650
- {
- mtailVAL.floats = make([]float64, 0)
- mtailVAL.floats = append(mtailVAL.floats, float64(mtailDollar[1].intVal))
- }
- case 116:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:655
- {
- mtailVAL.floats = mtailDollar[1].floats
- mtailVAL.floats = append(mtailVAL.floats, mtailDollar[3].floatVal)
- }
- case 117:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:660
- {
- mtailVAL.floats = mtailDollar[1].floats
- mtailVAL.floats = append(mtailVAL.floats, float64(mtailDollar[3].intVal))
- }
- case 118:
- mtailDollar = mtailS[mtailpt-4 : mtailpt+1]
-//line parser.y:668
- {
- mtailVAL.n = &ast.DecoDecl{P: markedpos(mtaillex), Name: mtailDollar[3].text, Block: mtailDollar[4].n}
- }
- case 119:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:676
- {
- mtailVAL.n = &ast.DecoStmt{markedpos(mtaillex), mtailDollar[2].text, mtailDollar[3].n, nil, nil}
- }
- case 120:
- mtailDollar = mtailS[mtailpt-5 : mtailpt+1]
-//line parser.y:684
- {
- mtailVAL.n = &ast.DelStmt{P: positionFromMark(mtaillex), N: mtailDollar[3].n, Expiry: mtailDollar[5].duration}
- }
- case 121:
- mtailDollar = mtailS[mtailpt-3 : mtailpt+1]
-//line parser.y:688
- {
- mtailVAL.n = &ast.DelStmt{P: positionFromMark(mtaillex), N: mtailDollar[3].n}
- }
- case 122:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:695
- {
- mtailVAL.text = mtailDollar[1].text
- }
- case 123:
- mtailDollar = mtailS[mtailpt-1 : mtailpt+1]
-//line parser.y:699
- {
- mtailVAL.text = mtailDollar[1].text
- }
- case 124:
- mtailDollar = mtailS[mtailpt-0 : mtailpt+1]
-//line parser.y:709
- {
- glog.V(2).Infof("position marked at %v", tokenpos(mtaillex))
- mtaillex.(*parser).pos = tokenpos(mtaillex)
- }
- case 125:
- mtailDollar = mtailS[mtailpt-0 : mtailpt+1]
-//line parser.y:719
- {
- mtaillex.(*parser).inRegex()
- }
- }
- goto mtailstack /* stack new state and value */
-}
diff --git a/internal/runtime/compiler/parser/parser.y b/internal/runtime/compiler/parser/parser.y
index b692a59b7..1af00b383 100644
--- a/internal/runtime/compiler/parser/parser.y
+++ b/internal/runtime/compiler/parser/parser.y
@@ -8,9 +8,9 @@ package parser
import (
"time"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
"github.com/golang/glog"
)
@@ -28,20 +28,22 @@ import (
n ast.Node
kind metrics.Kind
duration time.Duration
+ logFilter *ast.LogFilter // Add this field for *ast.LogFilter
}
%type stmt_list stmt arg_expr_list compound_stmt conditional_stmt conditional_expr expr_stmt
%type expr primary_expr multiplicative_expr additive_expr postfix_expr unary_expr assign_expr
-%type rel_expr shift_expr bitwise_expr logical_expr indexed_expr id_expr concat_expr pattern_expr
+%type rel_expr shift_expr bitwise_expr logical_expr indexed_expr id_expr concat_expr pattern_expr const_pattern concat_start
%type metric_declaration metric_decl_attr_spec decorator_declaration decoration_stmt regex_pattern match_expr
%type delete_stmt metric_name_spec builtin_expr arg_expr
%type metric_type_spec
%type metric_limit_spec
-%type metric_as_spec id_or_string metric_by_expr
-%type metric_by_spec metric_by_expr_list
+%type metric_as_spec id_or_string metric_by_expr log_filter_expr
+%type metric_by_spec metric_by_expr_list log_filter_list
%type metric_hide_spec
%type rel_op shift_op bitwise_op logical_op add_op mul_op match_op postfix_op
%type metric_buckets_spec metric_buckets_list
+%type log_filter_stmt
// Tokens and types are defined here.
// Invalid input
%token INVALID
@@ -73,6 +75,7 @@ import (
%token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE
%token COMMA
%token NL
+%token LOGFILTER
%start start
@@ -112,7 +115,9 @@ stmt_list
/* Types of statements. */
stmt
- : conditional_stmt
+ : log_filter_stmt
+ { $$ = $1 }
+ | conditional_stmt
{ $$ = $1 }
| expr_stmt
{ $$ = $1 }
@@ -128,7 +133,7 @@ stmt
{
$$ = &ast.NextStmt{tokenpos(mtaillex)}
}
- | CONST id_expr opt_nl concat_expr
+ | CONST id_expr opt_nl const_pattern
{
$$ = &ast.PatternFragment{ID: $2, Expr: $4}
}
@@ -142,6 +147,34 @@ stmt
}
;
+log_filter_stmt
+ : LOGFILTER log_filter_list
+ {
+ $$ = &ast.LogFilter{
+ P: tokenpos(mtaillex),
+ Filters: $2, // $2 is the list of strings (type []string)
+ }
+ }
+ ;
+
+log_filter_list
+ : log_filter_expr
+ {
+ $$ = make([]string, 0)
+ $$ = append($$, $1)
+ }
+ | log_filter_list COMMA log_filter_expr
+ {
+ $$ = $1
+ $$ = append($$, $3)
+ }
+ ;
+
+log_filter_expr
+ : id_or_string
+ { $$ = $1 }
+ ;
+
/* Conditional statement is a test condition, and then actions executed depending on the result of the test. */
conditional_stmt
: conditional_expr compound_stmt ELSE compound_stmt
@@ -176,6 +209,18 @@ conditional_expr
Op: $2,
}
}
+ | concat_start
+ {
+ $$ = &ast.UnaryExpr{P: tokenpos(mtaillex), Expr: &ast.PatternExpr{Expr: $1}, Op: MATCH}
+ }
+ | concat_start logical_op opt_nl logical_expr
+ {
+ $$ = &ast.BinaryExpr{
+ LHS: &ast.UnaryExpr{P: tokenpos(mtaillex), Expr: &ast.PatternExpr{Expr: $1}, Op: MATCH},
+ RHS: $4,
+ Op: $2,
+ }
+ }
| logical_expr
{ $$ = $1 }
;
@@ -327,6 +372,14 @@ match_expr
{
$$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: $2}
}
+ | primary_expr match_op opt_nl concat_start
+ {
+ $$ = &ast.BinaryExpr{
+ LHS: $1,
+ RHS: &ast.PatternExpr{Expr: $4},
+ Op: $2,
+ }
+ }
;
match_op
@@ -345,6 +398,42 @@ pattern_expr
}
;
+/* Const pattern fragment expression allows identifiers in addition to regex patterns. */
+const_pattern
+ : regex_pattern
+ { $$ = $1 }
+ | id_expr
+ { $$ = $1 }
+ | const_pattern PLUS opt_nl regex_pattern
+ {
+ $$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: PLUS}
+ }
+ | const_pattern PLUS opt_nl id_expr
+ {
+ $$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: PLUS}
+ }
+ ;
+
+/* Concatenation start expression handles id_expr at the start of a pattern concatenation. */
+concat_start
+ : id_expr PLUS opt_nl regex_pattern
+ {
+ $$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: PLUS}
+ }
+ | id_expr PLUS opt_nl id_expr
+ {
+ $$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: PLUS}
+ }
+ | concat_start PLUS opt_nl regex_pattern
+ {
+ $$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: PLUS}
+ }
+ | concat_start PLUS opt_nl id_expr
+ {
+ $$ = &ast.BinaryExpr{LHS: $1, RHS: $4, Op: PLUS}
+ }
+ ;
+
/* Concatenation expression forms a regular expression pattern from fragments. */
concat_expr
: regex_pattern
diff --git a/internal/runtime/compiler/parser/parser_test.go b/internal/runtime/compiler/parser/parser_test.go
index 4507da838..da03ee166 100644
--- a/internal/runtime/compiler/parser/parser_test.go
+++ b/internal/runtime/compiler/parser/parser_test.go
@@ -8,9 +8,9 @@ import (
"strings"
"testing"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var parserTestDebug = flag.Bool("parser_test_debug", false, "Turn on parser debug output if set.")
@@ -398,6 +398,36 @@ const X /foo/
{"concat expr 2", `
const X /foo/
X {
+}`},
+
+ {"concat start with id plus regex", `
+const A /foo/
+A + /bar/ {
+}`},
+ {"concat start with id plus id", `
+const X /foo/
+const Y /bar/
+X + Y {
+}`},
+ {"concat start multi", `
+const X /foo/
+const Y /bar/
+X + Y + /baz/ {
+}`},
+ {"concat start match", `
+const X /foo/
+$uri =~ X + /bar/ {
+}`},
+ {"const with id concat", `
+const A /foo/
+const B A + /bar/
+B {
+}`},
+ {"const with id id", `
+const A /foo/
+const B /bar/
+const C A + B
+C {
}`},
{"match expression 1", `
@@ -438,6 +468,35 @@ $foo =~ X {
/(\d,\d)/ {
subst(/,/, "", $1)
}`},
+ {
+ "log_filter",
+ "log_filter \"foo\", \"bar\", \"baz\"\n",
+ },
+ {
+ "log_filter no new line",
+ "log_filter \"foo\", \"bar\", \"baz\"",
+ },
+ {
+ "log_filter unquoted strings",
+ "log_filter foo, bar, baz",
+ },
+ {
+ "log_filter no spaces",
+ "log_filter foo,bar,baz",
+ },
+ {
+ "log_filter multiple lines",
+ `log_filter foo,bar,baz
+log_filter foo,bar,bee`,
+ },
+ {
+ "log_filter then a clause",
+ "log_filter \"foo\", \"bar\", \"baz\"\n/foo/ {} else {}",
+ },
+ {
+ "clause then a log_filter",
+ "/foo/ {} else {}\nlog_filter \"foo\", \"bar\", \"baz\"\n",
+ },
}
func TestParserRoundTrip(t *testing.T) {
@@ -507,7 +566,13 @@ var parserInvalidPrograms = []parserInvalidProgram{
"unterminated regex:1:2-4: syntax error: unexpected end of file, expecting '/' to end regex",
},
},
-
+ {
+ "log_filter empty",
+ `log_filter`,
+ []string{
+ "log_filter empty:1:11: syntax error: unexpected $end, expecting STRING or ID",
+ },
+ },
{
"unterminated string",
" \"foo }\n",
@@ -636,8 +701,7 @@ var parsePositionTests = []struct {
"const ID\n" +
"/foo/ +\n" +
"/bar/",
- // TODO: Update position for the first token to `1, 0, 4` when position tracking is fixed
- []*position.Position{{"multiline regex", 1, 4, 4}, {"multiline regex", 2, 0, 4}},
+ []*position.Position{{"multiline regex", 1, 0, 4}, {"multiline regex", 2, 0, 4}},
},
}
diff --git a/internal/runtime/compiler/parser/sexp.go b/internal/runtime/compiler/parser/sexp.go
index bc4171de3..fe8ae16e6 100644
--- a/internal/runtime/compiler/parser/sexp.go
+++ b/internal/runtime/compiler/parser/sexp.go
@@ -8,9 +8,9 @@ import (
"strconv"
"strings"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler/ast"
- "github.com/google/mtail/internal/runtime/compiler/symbol"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/symbol"
)
// Sexp is for converting program syntax trees into typed s-expression for printing.
@@ -62,6 +62,13 @@ func (s *Sexp) VisitBefore(n ast.Node) (ast.Visitor, ast.Node) {
s.indent()
switch v := n.(type) {
+ case *ast.LogFilter:
+ s.emit("log_filter ")
+ if len(v.Filters) > 0 {
+ s.emit(strings.Join(v.Filters, ", "))
+ }
+ s.newline()
+
case *ast.PatternFragment:
s.emit("const ")
ast.Walk(s, v.ID)
@@ -239,9 +246,11 @@ func (s *Sexp) emitScope(scope *symbol.Scope) {
}
if len(scope.Symbols) > 0 {
s.indent()
- for name, sym := range scope.Symbols {
- s.emit(fmt.Sprintf("%q: %v %q %v", name, sym.Kind, sym.Name, sym.Used))
- s.newline()
+ for name, syms := range scope.Symbols {
+ for _, sym := range syms {
+ s.emit(fmt.Sprintf("%q: %v %q %v", name, sym.Kind, sym.Name, sym.Used))
+ s.newline()
+ }
}
s.outdent()
}
diff --git a/internal/runtime/compiler/parser/tokens.go b/internal/runtime/compiler/parser/tokens.go
index 8f36cd5b1..2ba300710 100644
--- a/internal/runtime/compiler/parser/tokens.go
+++ b/internal/runtime/compiler/parser/tokens.go
@@ -6,7 +6,7 @@ package parser
import (
"fmt"
- "github.com/google/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
)
// Kind enumerates the types of lexical tokens in a mtail program.
diff --git a/internal/runtime/compiler/parser/tokens_test.go b/internal/runtime/compiler/parser/tokens_test.go
index 35b26f615..f66639a5e 100644
--- a/internal/runtime/compiler/parser/tokens_test.go
+++ b/internal/runtime/compiler/parser/tokens_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"testing/quick"
- "github.com/google/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
)
func TestKindHasString(t *testing.T) {
diff --git a/internal/runtime/compiler/parser/unparser.go b/internal/runtime/compiler/parser/unparser.go
index 979c3f711..5b28ffdd5 100644
--- a/internal/runtime/compiler/parser/unparser.go
+++ b/internal/runtime/compiler/parser/unparser.go
@@ -8,8 +8,8 @@ import (
"strconv"
"strings"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler/ast"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/ast"
)
// Unparser is for converting program syntax trees back to program text.
@@ -52,6 +52,14 @@ func (u *Unparser) VisitBefore(n ast.Node) (ast.Visitor, ast.Node) {
u.emit(fmt.Sprintf("<%s>(", n.Type()))
}
switch v := n.(type) {
+
+ case *ast.LogFilter:
+ u.emit("log_filter ")
+ if len(v.Filters) > 0 {
+ u.emit("\"" + strings.Join(v.Filters, "\", \"") + "\"")
+ }
+ u.newline()
+
case *ast.StmtList:
for _, child := range v.Children {
ast.Walk(u, child)
diff --git a/internal/runtime/compiler/parser/y.output b/internal/runtime/compiler/parser/y.output
deleted file mode 100644
index d7620a328..000000000
--- a/internal/runtime/compiler/parser/y.output
+++ /dev/null
@@ -1,1840 +0,0 @@
-
-state 0
- $accept: .start $end
- stmt_list: . (2)
-
- . reduce 2 (src line 99)
-
- stmt_list goto 2
- start goto 1
-
-state 1
- $accept: start.$end
-
- $end accept
- . error
-
-
-state 2
- start: stmt_list. (1)
- stmt_list: stmt_list.stmt
- mark_pos: . (124)
- metric_hide_spec: . (93)
-
- $end reduce 1 (src line 91)
- INVALID shift 13
- COUNTER reduce 93 (src line 520)
- GAUGE reduce 93 (src line 520)
- TIMER reduce 93 (src line 520)
- TEXT reduce 93 (src line 520)
- HISTOGRAM reduce 93 (src line 520)
- CONST shift 11
- HIDDEN shift 23
- NEXT shift 10
- STOP shift 12
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- NL shift 16
- . reduce 124 (src line 707)
-
- stmt goto 3
- conditional_stmt goto 4
- conditional_expr goto 14
- expr_stmt goto 5
- expr goto 17
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 22
- unary_expr goto 27
- assign_expr goto 21
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 20
- indexed_expr goto 32
- id_expr goto 41
- concat_expr goto 24
- pattern_expr goto 19
- metric_declaration goto 6
- decorator_declaration goto 7
- decoration_stmt goto 8
- regex_pattern goto 29
- match_expr goto 26
- delete_stmt goto 9
- builtin_expr goto 33
- metric_hide_spec goto 18
- mark_pos goto 15
-
-state 3
- stmt_list: stmt_list stmt. (3)
-
- . reduce 3 (src line 104)
-
-
-state 4
- stmt: conditional_stmt. (4)
-
- . reduce 4 (src line 114)
-
-
-state 5
- stmt: expr_stmt. (5)
-
- . reduce 5 (src line 117)
-
-
-state 6
- stmt: metric_declaration. (6)
-
- . reduce 6 (src line 119)
-
-
-state 7
- stmt: decorator_declaration. (7)
-
- . reduce 7 (src line 121)
-
-
-state 8
- stmt: decoration_stmt. (8)
-
- . reduce 8 (src line 123)
-
-
-state 9
- stmt: delete_stmt. (9)
-
- . reduce 9 (src line 125)
-
-
-state 10
- stmt: NEXT. (10)
-
- . reduce 10 (src line 127)
-
-
-state 11
- stmt: CONST.id_expr opt_nl concat_expr
-
- ID shift 43
- . error
-
- id_expr goto 45
-
-state 12
- stmt: STOP. (12)
-
- . reduce 12 (src line 135)
-
-
-state 13
- stmt: INVALID. (13)
-
- . reduce 13 (src line 139)
-
-
-state 14
- conditional_stmt: conditional_expr.compound_stmt ELSE compound_stmt
- conditional_stmt: conditional_expr.compound_stmt
-
- LCURLY shift 47
- . error
-
- compound_stmt goto 46
-
-state 15
- conditional_stmt: mark_pos.OTHERWISE compound_stmt
- builtin_expr: mark_pos.BUILTIN LPAREN RPAREN
- builtin_expr: mark_pos.BUILTIN LPAREN arg_expr_list RPAREN
- regex_pattern: mark_pos.DIV in_regex REGEX DIV
- decorator_declaration: mark_pos.DEF ID compound_stmt
- decoration_stmt: mark_pos.DECO compound_stmt
- delete_stmt: mark_pos.DEL postfix_expr AFTER DURATIONLITERAL
- delete_stmt: mark_pos.DEL postfix_expr
-
- DEF shift 51
- DEL shift 53
- OTHERWISE shift 48
- BUILTIN shift 49
- DECO shift 52
- DIV shift 50
- . error
-
-
-state 16
- expr_stmt: NL. (20)
-
- . reduce 20 (src line 184)
-
-
-state 17
- expr_stmt: expr.NL
-
- NL shift 54
- . error
-
-
-state 18
- metric_declaration: metric_hide_spec.metric_type_spec metric_decl_attr_spec
-
- COUNTER shift 56
- GAUGE shift 57
- TIMER shift 58
- TEXT shift 59
- HISTOGRAM shift 60
- . error
-
- metric_type_spec goto 55
-
-state 19
- conditional_expr: pattern_expr. (17)
- conditional_expr: pattern_expr.logical_op opt_nl logical_expr
-
- AND shift 62
- OR shift 63
- . reduce 17 (src line 166)
-
- logical_op goto 61
-
-state 20
- conditional_expr: logical_expr. (19)
- logical_expr: logical_expr.logical_op opt_nl bitwise_expr
- logical_expr: logical_expr.logical_op opt_nl match_expr
-
- AND shift 62
- OR shift 63
- . reduce 19 (src line 179)
-
- logical_op goto 64
-
-state 21
- expr: assign_expr. (23)
-
- . reduce 23 (src line 200)
-
-
-state 22
- expr: postfix_expr. (24)
- unary_expr: postfix_expr. (68)
- postfix_expr: postfix_expr.postfix_op
-
- INC shift 66
- DEC shift 67
- NL reduce 24 (src line 203)
- . reduce 68 (src line 384)
-
- postfix_op goto 65
-
-state 23
- metric_hide_spec: HIDDEN. (94)
-
- . reduce 94 (src line 525)
-
-
-state 24
- pattern_expr: concat_expr. (58)
- concat_expr: concat_expr.PLUS opt_nl regex_pattern
- concat_expr: concat_expr.PLUS opt_nl id_expr
-
- PLUS shift 68
- . reduce 58 (src line 341)
-
-
-state 25
- logical_expr: bitwise_expr. (27)
- bitwise_expr: bitwise_expr.bitwise_op opt_nl rel_expr
-
- BITAND shift 70
- XOR shift 72
- BITOR shift 71
- . reduce 27 (src line 220)
-
- bitwise_op goto 69
-
-state 26
- logical_expr: match_expr. (28)
-
- . reduce 28 (src line 223)
-
-
-state 27
- assign_expr: unary_expr.ASSIGN opt_nl logical_expr
- assign_expr: unary_expr.ADD_ASSIGN opt_nl logical_expr
- multiplicative_expr: unary_expr. (62)
-
- ADD_ASSIGN shift 74
- ASSIGN shift 73
- . reduce 62 (src line 363)
-
-
-state 28
- match_expr: primary_expr.match_op opt_nl pattern_expr
- match_expr: primary_expr.match_op opt_nl primary_expr
- postfix_expr: primary_expr. (70)
-
- MATCH shift 76
- NOT_MATCH shift 77
- . reduce 70 (src line 394)
-
- match_op goto 75
-
-state 29
- concat_expr: regex_pattern. (59)
-
- . reduce 59 (src line 349)
-
-
-state 30
- bitwise_expr: rel_expr. (33)
- rel_expr: rel_expr.rel_op opt_nl shift_expr
-
- LT shift 79
- GT shift 80
- LE shift 81
- GE shift 82
- EQ shift 83
- NE shift 84
- . reduce 33 (src line 243)
-
- rel_op goto 78
-
-state 31
- unary_expr: NOT.unary_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- postfix_expr goto 86
- unary_expr goto 85
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 32
- primary_expr: indexed_expr. (74)
- indexed_expr: indexed_expr.LSQUARE arg_expr_list RSQUARE
-
- LSQUARE shift 89
- . reduce 74 (src line 411)
-
-
-state 33
- primary_expr: builtin_expr. (75)
-
- . reduce 75 (src line 414)
-
-
-state 34
- primary_expr: CAPREF. (76)
-
- . reduce 76 (src line 416)
-
-
-state 35
- primary_expr: CAPREF_NAMED. (77)
-
- . reduce 77 (src line 420)
-
-
-state 36
- primary_expr: STRING. (78)
-
- . reduce 78 (src line 424)
-
-
-state 37
- primary_expr: LPAREN.logical_expr RPAREN
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 90
- indexed_expr goto 32
- id_expr goto 41
- match_expr goto 26
- builtin_expr goto 33
- mark_pos goto 88
-
-state 38
- primary_expr: INTLITERAL. (80)
-
- . reduce 80 (src line 432)
-
-
-state 39
- primary_expr: FLOATLITERAL. (81)
-
- . reduce 81 (src line 436)
-
-
-state 40
- rel_expr: shift_expr. (38)
- shift_expr: shift_expr.shift_op opt_nl additive_expr
-
- SHL shift 93
- SHR shift 94
- . reduce 38 (src line 262)
-
- shift_op goto 92
-
-state 41
- indexed_expr: id_expr. (82)
-
- . reduce 82 (src line 443)
-
-
-state 42
- shift_expr: additive_expr. (46)
- additive_expr: additive_expr.add_op opt_nl multiplicative_expr
-
- MINUS shift 97
- PLUS shift 96
- . reduce 46 (src line 287)
-
- add_op goto 95
-
-state 43
- id_expr: ID. (84)
-
- . reduce 84 (src line 459)
-
-
-state 44
- additive_expr: multiplicative_expr. (50)
- multiplicative_expr: multiplicative_expr.mul_op opt_nl unary_expr
-
- DIV shift 100
- MOD shift 101
- MUL shift 99
- POW shift 102
- . reduce 50 (src line 304)
-
- mul_op goto 98
-
-state 45
- stmt: CONST id_expr.opt_nl concat_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 103
-
-state 46
- conditional_stmt: conditional_expr compound_stmt.ELSE compound_stmt
- conditional_stmt: conditional_expr compound_stmt. (15)
-
- ELSE shift 105
- . reduce 15 (src line 151)
-
-
-state 47
- compound_stmt: LCURLY.stmt_list RCURLY
- stmt_list: . (2)
-
- . reduce 2 (src line 99)
-
- stmt_list goto 106
-
-state 48
- conditional_stmt: mark_pos OTHERWISE.compound_stmt
-
- LCURLY shift 47
- . error
-
- compound_stmt goto 107
-
-state 49
- builtin_expr: mark_pos BUILTIN.LPAREN RPAREN
- builtin_expr: mark_pos BUILTIN.LPAREN arg_expr_list RPAREN
-
- LPAREN shift 108
- . error
-
-
-state 50
- regex_pattern: mark_pos DIV.in_regex REGEX DIV
- in_regex: . (125)
-
- . reduce 125 (src line 717)
-
- in_regex goto 109
-
-state 51
- decorator_declaration: mark_pos DEF.ID compound_stmt
-
- ID shift 110
- . error
-
-
-state 52
- decoration_stmt: mark_pos DECO.compound_stmt
-
- LCURLY shift 47
- . error
-
- compound_stmt goto 111
-
-state 53
- delete_stmt: mark_pos DEL.postfix_expr AFTER DURATIONLITERAL
- delete_stmt: mark_pos DEL.postfix_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- postfix_expr goto 112
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 54
- expr_stmt: expr NL. (21)
-
- . reduce 21 (src line 187)
-
-
-state 55
- metric_declaration: metric_hide_spec metric_type_spec.metric_decl_attr_spec
-
- STRING shift 116
- ID shift 115
- . error
-
- metric_decl_attr_spec goto 113
- metric_name_spec goto 114
-
-state 56
- metric_type_spec: COUNTER. (102)
-
- . reduce 102 (src line 572)
-
-
-state 57
- metric_type_spec: GAUGE. (103)
-
- . reduce 103 (src line 577)
-
-
-state 58
- metric_type_spec: TIMER. (104)
-
- . reduce 104 (src line 581)
-
-
-state 59
- metric_type_spec: TEXT. (105)
-
- . reduce 105 (src line 585)
-
-
-state 60
- metric_type_spec: HISTOGRAM. (106)
-
- . reduce 106 (src line 589)
-
-
-state 61
- conditional_expr: pattern_expr logical_op.opt_nl logical_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 117
-
-state 62
- logical_op: AND. (31)
-
- . reduce 31 (src line 235)
-
-
-state 63
- logical_op: OR. (32)
-
- . reduce 32 (src line 238)
-
-
-state 64
- logical_expr: logical_expr logical_op.opt_nl bitwise_expr
- logical_expr: logical_expr logical_op.opt_nl match_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 118
-
-state 65
- postfix_expr: postfix_expr postfix_op. (71)
-
- . reduce 71 (src line 397)
-
-
-state 66
- postfix_op: INC. (72)
-
- . reduce 72 (src line 403)
-
-
-state 67
- postfix_op: DEC. (73)
-
- . reduce 73 (src line 406)
-
-
-state 68
- concat_expr: concat_expr PLUS.opt_nl regex_pattern
- concat_expr: concat_expr PLUS.opt_nl id_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 119
-
-state 69
- bitwise_expr: bitwise_expr bitwise_op.opt_nl rel_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 120
-
-state 70
- bitwise_op: BITAND. (35)
-
- . reduce 35 (src line 252)
-
-
-state 71
- bitwise_op: BITOR. (36)
-
- . reduce 36 (src line 255)
-
-
-state 72
- bitwise_op: XOR. (37)
-
- . reduce 37 (src line 257)
-
-
-state 73
- assign_expr: unary_expr ASSIGN.opt_nl logical_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 121
-
-state 74
- assign_expr: unary_expr ADD_ASSIGN.opt_nl logical_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 122
-
-state 75
- match_expr: primary_expr match_op.opt_nl pattern_expr
- match_expr: primary_expr match_op.opt_nl primary_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 123
-
-state 76
- match_op: MATCH. (56)
-
- . reduce 56 (src line 332)
-
-
-state 77
- match_op: NOT_MATCH. (57)
-
- . reduce 57 (src line 335)
-
-
-state 78
- rel_expr: rel_expr rel_op.opt_nl shift_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 124
-
-state 79
- rel_op: LT. (40)
-
- . reduce 40 (src line 271)
-
-
-state 80
- rel_op: GT. (41)
-
- . reduce 41 (src line 274)
-
-
-state 81
- rel_op: LE. (42)
-
- . reduce 42 (src line 276)
-
-
-state 82
- rel_op: GE. (43)
-
- . reduce 43 (src line 278)
-
-
-state 83
- rel_op: EQ. (44)
-
- . reduce 44 (src line 280)
-
-
-state 84
- rel_op: NE. (45)
-
- . reduce 45 (src line 282)
-
-
-state 85
- unary_expr: NOT unary_expr. (69)
-
- . reduce 69 (src line 387)
-
-
-state 86
- unary_expr: postfix_expr. (68)
- postfix_expr: postfix_expr.postfix_op
-
- INC shift 66
- DEC shift 67
- . reduce 68 (src line 384)
-
- postfix_op goto 65
-
-state 87
- postfix_expr: primary_expr. (70)
-
- . reduce 70 (src line 394)
-
-
-state 88
- builtin_expr: mark_pos.BUILTIN LPAREN RPAREN
- builtin_expr: mark_pos.BUILTIN LPAREN arg_expr_list RPAREN
-
- BUILTIN shift 49
- . error
-
-
-state 89
- indexed_expr: indexed_expr LSQUARE.arg_expr_list RSQUARE
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- arg_expr_list goto 125
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 127
- indexed_expr goto 32
- id_expr goto 41
- concat_expr goto 24
- pattern_expr goto 128
- regex_pattern goto 29
- match_expr goto 26
- builtin_expr goto 33
- arg_expr goto 126
- mark_pos goto 129
-
-state 90
- logical_expr: logical_expr.logical_op opt_nl bitwise_expr
- logical_expr: logical_expr.logical_op opt_nl match_expr
- primary_expr: LPAREN logical_expr.RPAREN
-
- AND shift 62
- OR shift 63
- RPAREN shift 130
- . error
-
- logical_op goto 64
-
-state 91
- multiplicative_expr: unary_expr. (62)
-
- . reduce 62 (src line 363)
-
-
-state 92
- shift_expr: shift_expr shift_op.opt_nl additive_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 131
-
-state 93
- shift_op: SHL. (48)
-
- . reduce 48 (src line 296)
-
-
-state 94
- shift_op: SHR. (49)
-
- . reduce 49 (src line 299)
-
-
-state 95
- additive_expr: additive_expr add_op.opt_nl multiplicative_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 132
-
-state 96
- add_op: PLUS. (52)
-
- . reduce 52 (src line 313)
-
-
-state 97
- add_op: MINUS. (53)
-
- . reduce 53 (src line 316)
-
-
-state 98
- multiplicative_expr: multiplicative_expr mul_op.opt_nl unary_expr
- opt_nl: . (126)
-
- NL shift 104
- . reduce 126 (src line 727)
-
- opt_nl goto 133
-
-state 99
- mul_op: MUL. (64)
-
- . reduce 64 (src line 372)
-
-
-state 100
- mul_op: DIV. (65)
-
- . reduce 65 (src line 375)
-
-
-state 101
- mul_op: MOD. (66)
-
- . reduce 66 (src line 377)
-
-
-state 102
- mul_op: POW. (67)
-
- . reduce 67 (src line 379)
-
-
-state 103
- stmt: CONST id_expr opt_nl.concat_expr
- mark_pos: . (124)
-
- . reduce 124 (src line 707)
-
- concat_expr goto 134
- regex_pattern goto 29
- mark_pos goto 135
-
-state 104
- opt_nl: NL. (127)
-
- . reduce 127 (src line 729)
-
-
-state 105
- conditional_stmt: conditional_expr compound_stmt ELSE.compound_stmt
-
- LCURLY shift 47
- . error
-
- compound_stmt goto 136
-
-state 106
- stmt_list: stmt_list.stmt
- compound_stmt: LCURLY stmt_list.RCURLY
- mark_pos: . (124)
- metric_hide_spec: . (93)
-
- INVALID shift 13
- COUNTER reduce 93 (src line 520)
- GAUGE reduce 93 (src line 520)
- TIMER reduce 93 (src line 520)
- TEXT reduce 93 (src line 520)
- HISTOGRAM reduce 93 (src line 520)
- CONST shift 11
- HIDDEN shift 23
- NEXT shift 10
- STOP shift 12
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- RCURLY shift 137
- LPAREN shift 37
- NL shift 16
- . reduce 124 (src line 707)
-
- stmt goto 3
- conditional_stmt goto 4
- conditional_expr goto 14
- expr_stmt goto 5
- expr goto 17
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 22
- unary_expr goto 27
- assign_expr goto 21
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 20
- indexed_expr goto 32
- id_expr goto 41
- concat_expr goto 24
- pattern_expr goto 19
- metric_declaration goto 6
- decorator_declaration goto 7
- decoration_stmt goto 8
- regex_pattern goto 29
- match_expr goto 26
- delete_stmt goto 9
- builtin_expr goto 33
- metric_hide_spec goto 18
- mark_pos goto 15
-
-state 107
- conditional_stmt: mark_pos OTHERWISE compound_stmt. (16)
-
- . reduce 16 (src line 159)
-
-
-state 108
- builtin_expr: mark_pos BUILTIN LPAREN.RPAREN
- builtin_expr: mark_pos BUILTIN LPAREN.arg_expr_list RPAREN
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- RPAREN shift 138
- . reduce 124 (src line 707)
-
- arg_expr_list goto 139
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 127
- indexed_expr goto 32
- id_expr goto 41
- concat_expr goto 24
- pattern_expr goto 128
- regex_pattern goto 29
- match_expr goto 26
- builtin_expr goto 33
- arg_expr goto 126
- mark_pos goto 129
-
-state 109
- regex_pattern: mark_pos DIV in_regex.REGEX DIV
-
- REGEX shift 140
- . error
-
-
-state 110
- decorator_declaration: mark_pos DEF ID.compound_stmt
-
- LCURLY shift 47
- . error
-
- compound_stmt goto 141
-
-state 111
- decoration_stmt: mark_pos DECO compound_stmt. (119)
-
- . reduce 119 (src line 674)
-
-
-state 112
- postfix_expr: postfix_expr.postfix_op
- delete_stmt: mark_pos DEL postfix_expr.AFTER DURATIONLITERAL
- delete_stmt: mark_pos DEL postfix_expr. (121)
-
- AFTER shift 142
- INC shift 66
- DEC shift 67
- . reduce 121 (src line 687)
-
- postfix_op goto 65
-
-state 113
- metric_declaration: metric_hide_spec metric_type_spec metric_decl_attr_spec. (92)
- metric_decl_attr_spec: metric_decl_attr_spec.metric_by_spec
- metric_decl_attr_spec: metric_decl_attr_spec.metric_as_spec
- metric_decl_attr_spec: metric_decl_attr_spec.metric_buckets_spec
- metric_decl_attr_spec: metric_decl_attr_spec.metric_limit_spec
-
- AS shift 148
- BY shift 147
- BUCKETS shift 149
- LIMIT shift 150
- . reduce 92 (src line 509)
-
- metric_limit_spec goto 146
- metric_as_spec goto 144
- metric_by_spec goto 143
- metric_buckets_spec goto 145
-
-state 114
- metric_decl_attr_spec: metric_name_spec. (99)
-
- . reduce 99 (src line 553)
-
-
-state 115
- metric_name_spec: ID. (100)
-
- . reduce 100 (src line 560)
-
-
-state 116
- metric_name_spec: STRING. (101)
-
- . reduce 101 (src line 565)
-
-
-state 117
- conditional_expr: pattern_expr logical_op opt_nl.logical_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 151
- indexed_expr goto 32
- id_expr goto 41
- match_expr goto 26
- builtin_expr goto 33
- mark_pos goto 88
-
-state 118
- logical_expr: logical_expr logical_op opt_nl.bitwise_expr
- logical_expr: logical_expr logical_op opt_nl.match_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 152
- indexed_expr goto 32
- id_expr goto 41
- match_expr goto 153
- builtin_expr goto 33
- mark_pos goto 88
-
-state 119
- concat_expr: concat_expr PLUS opt_nl.regex_pattern
- concat_expr: concat_expr PLUS opt_nl.id_expr
- mark_pos: . (124)
-
- ID shift 43
- . reduce 124 (src line 707)
-
- id_expr goto 155
- regex_pattern goto 154
- mark_pos goto 135
-
-state 120
- bitwise_expr: bitwise_expr bitwise_op opt_nl.rel_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 156
- shift_expr goto 40
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 121
- assign_expr: unary_expr ASSIGN opt_nl.logical_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 157
- indexed_expr goto 32
- id_expr goto 41
- match_expr goto 26
- builtin_expr goto 33
- mark_pos goto 88
-
-state 122
- assign_expr: unary_expr ADD_ASSIGN opt_nl.logical_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 158
- indexed_expr goto 32
- id_expr goto 41
- match_expr goto 26
- builtin_expr goto 33
- mark_pos goto 88
-
-state 123
- match_expr: primary_expr match_op opt_nl.pattern_expr
- match_expr: primary_expr match_op opt_nl.primary_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 160
- indexed_expr goto 32
- id_expr goto 41
- concat_expr goto 24
- pattern_expr goto 159
- regex_pattern goto 29
- builtin_expr goto 33
- mark_pos goto 129
-
-state 124
- rel_expr: rel_expr rel_op opt_nl.shift_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- shift_expr goto 161
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 125
- indexed_expr: indexed_expr LSQUARE arg_expr_list.RSQUARE
- arg_expr_list: arg_expr_list.COMMA arg_expr
-
- RSQUARE shift 162
- COMMA shift 163
- . error
-
-
-state 126
- arg_expr_list: arg_expr. (87)
-
- . reduce 87 (src line 480)
-
-
-state 127
- logical_expr: logical_expr.logical_op opt_nl bitwise_expr
- logical_expr: logical_expr.logical_op opt_nl match_expr
- arg_expr: logical_expr. (89)
-
- AND shift 62
- OR shift 63
- . reduce 89 (src line 493)
-
- logical_op goto 64
-
-state 128
- arg_expr: pattern_expr. (90)
-
- . reduce 90 (src line 496)
-
-
-state 129
- builtin_expr: mark_pos.BUILTIN LPAREN RPAREN
- builtin_expr: mark_pos.BUILTIN LPAREN arg_expr_list RPAREN
- regex_pattern: mark_pos.DIV in_regex REGEX DIV
-
- BUILTIN shift 49
- DIV shift 50
- . error
-
-
-state 130
- primary_expr: LPAREN logical_expr RPAREN. (79)
-
- . reduce 79 (src line 428)
-
-
-state 131
- shift_expr: shift_expr shift_op opt_nl.additive_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- multiplicative_expr goto 44
- additive_expr goto 164
- postfix_expr goto 86
- unary_expr goto 91
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 132
- additive_expr: additive_expr add_op opt_nl.multiplicative_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- multiplicative_expr goto 165
- postfix_expr goto 86
- unary_expr goto 91
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 133
- multiplicative_expr: multiplicative_expr mul_op opt_nl.unary_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 87
- postfix_expr goto 86
- unary_expr goto 166
- indexed_expr goto 32
- id_expr goto 41
- builtin_expr goto 33
- mark_pos goto 88
-
-state 134
- stmt: CONST id_expr opt_nl concat_expr. (11)
- concat_expr: concat_expr.PLUS opt_nl regex_pattern
- concat_expr: concat_expr.PLUS opt_nl id_expr
-
- PLUS shift 68
- . reduce 11 (src line 131)
-
-
-state 135
- regex_pattern: mark_pos.DIV in_regex REGEX DIV
-
- DIV shift 50
- . error
-
-
-state 136
- conditional_stmt: conditional_expr compound_stmt ELSE compound_stmt. (14)
-
- . reduce 14 (src line 146)
-
-
-state 137
- compound_stmt: LCURLY stmt_list RCURLY. (22)
-
- . reduce 22 (src line 192)
-
-
-state 138
- builtin_expr: mark_pos BUILTIN LPAREN RPAREN. (85)
-
- . reduce 85 (src line 467)
-
-
-state 139
- builtin_expr: mark_pos BUILTIN LPAREN arg_expr_list.RPAREN
- arg_expr_list: arg_expr_list.COMMA arg_expr
-
- RPAREN shift 167
- COMMA shift 163
- . error
-
-
-state 140
- regex_pattern: mark_pos DIV in_regex REGEX.DIV
-
- DIV shift 168
- . error
-
-
-state 141
- decorator_declaration: mark_pos DEF ID compound_stmt. (118)
-
- . reduce 118 (src line 666)
-
-
-state 142
- delete_stmt: mark_pos DEL postfix_expr AFTER.DURATIONLITERAL
-
- DURATIONLITERAL shift 169
- . error
-
-
-state 143
- metric_decl_attr_spec: metric_decl_attr_spec metric_by_spec. (95)
-
- . reduce 95 (src line 532)
-
-
-state 144
- metric_decl_attr_spec: metric_decl_attr_spec metric_as_spec. (96)
-
- . reduce 96 (src line 538)
-
-
-state 145
- metric_decl_attr_spec: metric_decl_attr_spec metric_buckets_spec. (97)
-
- . reduce 97 (src line 543)
-
-
-state 146
- metric_decl_attr_spec: metric_decl_attr_spec metric_limit_spec. (98)
-
- . reduce 98 (src line 548)
-
-
-state 147
- metric_by_spec: BY.metric_by_expr_list
-
- STRING shift 174
- ID shift 173
- . error
-
- id_or_string goto 172
- metric_by_expr goto 171
- metric_by_expr_list goto 170
-
-state 148
- metric_as_spec: AS.STRING
-
- STRING shift 175
- . error
-
-
-state 149
- metric_buckets_spec: BUCKETS.metric_buckets_list
-
- INTLITERAL shift 178
- FLOATLITERAL shift 177
- . error
-
- metric_buckets_list goto 176
-
-state 150
- metric_limit_spec: LIMIT.INTLITERAL
-
- INTLITERAL shift 179
- . error
-
-
-state 151
- conditional_expr: pattern_expr logical_op opt_nl logical_expr. (18)
- logical_expr: logical_expr.logical_op opt_nl bitwise_expr
- logical_expr: logical_expr.logical_op opt_nl match_expr
-
- AND shift 62
- OR shift 63
- . reduce 18 (src line 171)
-
- logical_op goto 64
-
-state 152
- logical_expr: logical_expr logical_op opt_nl bitwise_expr. (29)
- bitwise_expr: bitwise_expr.bitwise_op opt_nl rel_expr
-
- BITAND shift 70
- XOR shift 72
- BITOR shift 71
- . reduce 29 (src line 225)
-
- bitwise_op goto 69
-
-state 153
- logical_expr: logical_expr logical_op opt_nl match_expr. (30)
-
- . reduce 30 (src line 229)
-
-
-state 154
- concat_expr: concat_expr PLUS opt_nl regex_pattern. (60)
-
- . reduce 60 (src line 352)
-
-
-state 155
- concat_expr: concat_expr PLUS opt_nl id_expr. (61)
-
- . reduce 61 (src line 356)
-
-
-state 156
- bitwise_expr: bitwise_expr bitwise_op opt_nl rel_expr. (34)
- rel_expr: rel_expr.rel_op opt_nl shift_expr
-
- LT shift 79
- GT shift 80
- LE shift 81
- GE shift 82
- EQ shift 83
- NE shift 84
- . reduce 34 (src line 246)
-
- rel_op goto 78
-
-state 157
- assign_expr: unary_expr ASSIGN opt_nl logical_expr. (25)
- logical_expr: logical_expr.logical_op opt_nl bitwise_expr
- logical_expr: logical_expr.logical_op opt_nl match_expr
-
- AND shift 62
- OR shift 63
- . reduce 25 (src line 208)
-
- logical_op goto 64
-
-state 158
- assign_expr: unary_expr ADD_ASSIGN opt_nl logical_expr. (26)
- logical_expr: logical_expr.logical_op opt_nl bitwise_expr
- logical_expr: logical_expr.logical_op opt_nl match_expr
-
- AND shift 62
- OR shift 63
- . reduce 26 (src line 213)
-
- logical_op goto 64
-
-state 159
- match_expr: primary_expr match_op opt_nl pattern_expr. (54)
-
- . reduce 54 (src line 321)
-
-
-state 160
- match_expr: primary_expr match_op opt_nl primary_expr. (55)
-
- . reduce 55 (src line 326)
-
-
-state 161
- rel_expr: rel_expr rel_op opt_nl shift_expr. (39)
- shift_expr: shift_expr.shift_op opt_nl additive_expr
-
- SHL shift 93
- SHR shift 94
- . reduce 39 (src line 265)
-
- shift_op goto 92
-
-state 162
- indexed_expr: indexed_expr LSQUARE arg_expr_list RSQUARE. (83)
-
- . reduce 83 (src line 449)
-
-
-state 163
- arg_expr_list: arg_expr_list COMMA.arg_expr
- mark_pos: . (124)
-
- STRING shift 36
- CAPREF shift 34
- CAPREF_NAMED shift 35
- ID shift 43
- INTLITERAL shift 38
- FLOATLITERAL shift 39
- NOT shift 31
- LPAREN shift 37
- . reduce 124 (src line 707)
-
- primary_expr goto 28
- multiplicative_expr goto 44
- additive_expr goto 42
- postfix_expr goto 86
- unary_expr goto 91
- rel_expr goto 30
- shift_expr goto 40
- bitwise_expr goto 25
- logical_expr goto 127
- indexed_expr goto 32
- id_expr goto 41
- concat_expr goto 24
- pattern_expr goto 128
- regex_pattern goto 29
- match_expr goto 26
- builtin_expr goto 33
- arg_expr goto 180
- mark_pos goto 129
-
-state 164
- shift_expr: shift_expr shift_op opt_nl additive_expr. (47)
- additive_expr: additive_expr.add_op opt_nl multiplicative_expr
-
- MINUS shift 97
- PLUS shift 96
- . reduce 47 (src line 290)
-
- add_op goto 95
-
-state 165
- additive_expr: additive_expr add_op opt_nl multiplicative_expr. (51)
- multiplicative_expr: multiplicative_expr.mul_op opt_nl unary_expr
-
- DIV shift 100
- MOD shift 101
- MUL shift 99
- POW shift 102
- . reduce 51 (src line 307)
-
- mul_op goto 98
-
-state 166
- multiplicative_expr: multiplicative_expr mul_op opt_nl unary_expr. (63)
-
- . reduce 63 (src line 366)
-
-
-state 167
- builtin_expr: mark_pos BUILTIN LPAREN arg_expr_list RPAREN. (86)
-
- . reduce 86 (src line 472)
-
-
-state 168
- regex_pattern: mark_pos DIV in_regex REGEX DIV. (91)
-
- . reduce 91 (src line 501)
-
-
-state 169
- delete_stmt: mark_pos DEL postfix_expr AFTER DURATIONLITERAL. (120)
-
- . reduce 120 (src line 682)
-
-
-state 170
- metric_by_spec: BY metric_by_expr_list. (107)
- metric_by_expr_list: metric_by_expr_list.COMMA metric_by_expr
-
- COMMA shift 181
- . reduce 107 (src line 596)
-
-
-state 171
- metric_by_expr_list: metric_by_expr. (108)
-
- . reduce 108 (src line 603)
-
-
-state 172
- metric_by_expr: id_or_string. (110)
-
- . reduce 110 (src line 616)
-
-
-state 173
- id_or_string: ID. (122)
-
- . reduce 122 (src line 693)
-
-
-state 174
- id_or_string: STRING. (123)
-
- . reduce 123 (src line 698)
-
-
-state 175
- metric_as_spec: AS STRING. (111)
-
- . reduce 111 (src line 622)
-
-
-state 176
- metric_buckets_spec: BUCKETS metric_buckets_list. (113)
- metric_buckets_list: metric_buckets_list.COMMA FLOATLITERAL
- metric_buckets_list: metric_buckets_list.COMMA INTLITERAL
-
- COMMA shift 182
- . reduce 113 (src line 637)
-
-
-state 177
- metric_buckets_list: FLOATLITERAL. (114)
-
- . reduce 114 (src line 643)
-
-
-state 178
- metric_buckets_list: INTLITERAL. (115)
-
- . reduce 115 (src line 649)
-
-
-state 179
- metric_limit_spec: LIMIT INTLITERAL. (112)
-
- . reduce 112 (src line 629)
-
-
-state 180
- arg_expr_list: arg_expr_list COMMA arg_expr. (88)
-
- . reduce 88 (src line 486)
-
-
-state 181
- metric_by_expr_list: metric_by_expr_list COMMA.metric_by_expr
-
- STRING shift 174
- ID shift 173
- . error
-
- id_or_string goto 172
- metric_by_expr goto 183
-
-state 182
- metric_buckets_list: metric_buckets_list COMMA.FLOATLITERAL
- metric_buckets_list: metric_buckets_list COMMA.INTLITERAL
-
- INTLITERAL shift 185
- FLOATLITERAL shift 184
- . error
-
-
-state 183
- metric_by_expr_list: metric_by_expr_list COMMA metric_by_expr. (109)
-
- . reduce 109 (src line 609)
-
-
-state 184
- metric_buckets_list: metric_buckets_list COMMA FLOATLITERAL. (116)
-
- . reduce 116 (src line 654)
-
-
-state 185
- metric_buckets_list: metric_buckets_list COMMA INTLITERAL. (117)
-
- . reduce 117 (src line 659)
-
-
-66 terminals, 55 nonterminals
-128 grammar rules, 186/16000 states
-0 shift/reduce, 0 reduce/reduce conflicts reported
-104 working sets used
-memory: parser 397/240000
-169 extra closures
-282 shift entries, 13 exceptions
-116 goto entries
-193 entries saved by goto default
-Optimizer space used: output 249/240000
-249 table entries, 2 zero
-maximum spread: 66, maximum offset: 181
diff --git a/internal/runtime/compiler/position/BUILD.bazel b/internal/runtime/compiler/position/BUILD.bazel
new file mode 100644
index 000000000..e3b553889
--- /dev/null
+++ b/internal/runtime/compiler/position/BUILD.bazel
@@ -0,0 +1,8 @@
+load("@rules_go//go:def.bzl", "go_library")
+
+go_library(
+ name = "position",
+ srcs = ["position.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/position",
+ visibility = ["//:__subpackages__"],
+)
diff --git a/internal/runtime/compiler/position/position.go b/internal/runtime/compiler/position/position.go
index 714ff1704..11c9e1f61 100644
--- a/internal/runtime/compiler/position/position.go
+++ b/internal/runtime/compiler/position/position.go
@@ -50,3 +50,16 @@ func Merge(a, b *Position) *Position {
}
return &r
}
+
+func (p Position) Equal(q Position) bool {
+ if p.Line != q.Line {
+ return false
+ }
+ if p.Startcol != q.Startcol {
+ return false
+ }
+ if p.Endcol != q.Endcol {
+ return false
+ }
+ return p.Filename == q.Filename
+}
diff --git a/internal/runtime/compiler/symbol/BUILD.bazel b/internal/runtime/compiler/symbol/BUILD.bazel
new file mode 100644
index 000000000..1a71eadcb
--- /dev/null
+++ b/internal/runtime/compiler/symbol/BUILD.bazel
@@ -0,0 +1,28 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "symbol",
+ srcs = ["symtab.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/symbol",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/runtime/compiler/errors",
+ "//internal/runtime/compiler/position",
+ "//internal/runtime/compiler/types",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "symbol_test",
+ size = "small",
+ srcs = ["symtab_test.go"],
+ embed = [":symbol"],
+ deps = [
+ "//internal/runtime/compiler/errors",
+ "//internal/runtime/compiler/position",
+ "//internal/testutil",
+ "@com_github_google_go_cmp//cmp",
+ "@com_github_google_go_cmp//cmp/cmpopts",
+ ],
+)
diff --git a/internal/runtime/compiler/symbol/symtab.go b/internal/runtime/compiler/symbol/symtab.go
index 541a5da63..fc14c450b 100644
--- a/internal/runtime/compiler/symbol/symtab.go
+++ b/internal/runtime/compiler/symbol/symtab.go
@@ -6,9 +6,12 @@ package symbol
import (
"bytes"
"fmt"
+ "strconv"
- "github.com/google/mtail/internal/runtime/compiler/position"
- "github.com/google/mtail/internal/runtime/compiler/types"
+ "github.com/golang/glog"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/types"
)
// Kind enumerates the kind of a Symbol.
@@ -55,44 +58,48 @@ func NewSymbol(name string, kind Kind, pos *position.Position) (sym *Symbol) {
}
// Scope maintains a record of the identifiers declared in the current program
-// scope, and a link to the parent scope.
+// scope, and a link to the parent scope. A program can insert multiple
+// symbols with the same identifier into the symbol table; multiple definition
+// errors are detected by `Check`, below.
type Scope struct {
Parent *Scope
- Symbols map[string]*Symbol
+ Symbols map[string][]*Symbol
}
// NewScope creates a new scope within the parent scope.
func NewScope(parent *Scope) *Scope {
- return &Scope{parent, make(map[string]*Symbol)}
+ return &Scope{parent, make(map[string][]*Symbol)}
}
// Insert attempts to insert a symbol into the scope. If the scope already
-// contains an object alt with the same name, the scope is unchanged and the
-// function returns alt. Otherwise the symbol is inserted, and returns nil.
+// contains a symbol with the same name, the new symbol is appended to the
+// list.
func (s *Scope) Insert(sym *Symbol) (alt *Symbol) {
- if alt = s.Symbols[sym.Name]; alt == nil {
- s.Symbols[sym.Name] = sym
+ if len(s.Symbols[sym.Name]) > 0 {
+ alt = s.Symbols[sym.Name][0]
}
+ s.Symbols[sym.Name] = append(s.Symbols[sym.Name], sym)
return
}
// InsertAlias attempts to insert a duplicate name for an existing symbol into
-// the scope. If the scope already contains an object alt with the alias, the
-// scope is unchanged and the function returns alt. Otherwise, the symbol is
-// inserted and the function returns nil.
+// the scope.
func (s *Scope) InsertAlias(sym *Symbol, alias string) (alt *Symbol) {
- if alt := s.Symbols[alias]; alt == nil {
- s.Symbols[alias] = sym
+ if len(s.Symbols[alias]) > 0 {
+ alt = s.Symbols[alias][0]
}
+ s.Symbols[alias] = append(s.Symbols[alias], sym)
return
}
// Lookup returns the symbol with the given name if it is found in this or any
-// parent scope, otherwise nil.
+// parent scope, otherwise nil. If the symbol has more than one definition,
+// the first registered symbol is returned.
func (s *Scope) Lookup(name string, kind Kind) *Symbol {
for scope := s; scope != nil; scope = scope.Parent {
- if sym := scope.Symbols[name]; sym != nil && sym.Kind == kind {
- return sym
+ symList := scope.Symbols[name]
+ if len(symList) > 0 && symList[0].Kind == kind {
+ return symList[0]
}
}
return nil
@@ -107,7 +114,9 @@ func (s *Scope) String() string {
fmt.Fprintln(&buf)
if len(s.Symbols) > 0 {
for name, sym := range s.Symbols {
- fmt.Fprintf(&buf, "\t%q: %v %q %v\n", name, sym.Kind, sym.Name, sym.Used)
+ for _, s := range sym {
+ fmt.Fprintf(&buf, "\t%q: %v %q %v\n", name, s.Kind, s.Name, s.Used)
+ }
}
}
if s.Parent != nil {
@@ -121,10 +130,46 @@ func (s *Scope) String() string {
// CopyFrom copies all the symbols from another scope object into this one.
// It recurses up the input scope copying all visible symbols into one.
func (s *Scope) CopyFrom(o *Scope) {
- for _, sym := range o.Symbols {
- s.Insert(sym)
+ for _, syms := range o.Symbols {
+ for _, sym := range syms {
+ s.Insert(sym)
+ }
}
if o.Parent != nil {
s.CopyFrom(o.Parent)
}
}
+
+// Check checks a symbol table for validity and emits errors into the given error list if any are found.
+func (s *Scope) Check(errors *errors.ErrorList) {
+ for _, symList := range s.Symbols {
+ multiple := len(symList) > 1
+ for i, sym := range symList {
+ if multiple && i > 0 {
+ if sym.Kind == CaprefSymbol {
+ // Numbered caprefs may be redeclared in chained
+ // match expressions (last pattern wins).
+ if _, err := strconv.Atoi(sym.Name); err == nil {
+ continue
+ }
+ }
+ errors.Add(sym.Pos, fmt.Sprintf("Redeclaration of %s `%s' previously declared at %s", sym.Kind, sym.Name, symList[0].Pos))
+ continue
+ }
+ if !sym.Used {
+ // Users don't have control over the patterns given from decorators
+ // so this should never be an error; but it can be useful to know
+ // if a program is doing unnecessary work.
+ if sym.Kind == CaprefSymbol {
+ if sym.Addr == 0 {
+ // Don't warn about the zeroth capture group; it's not user-defined.
+ continue
+ }
+ glog.Infof("capture group reference `%s' at %s appears to be unused", sym.Name, sym.Pos)
+ continue
+ }
+ errors.Add(sym.Pos, fmt.Sprintf("Declaration of %s `%s' here is never used.", sym.Kind, sym.Name))
+ }
+ }
+ }
+}
diff --git a/internal/runtime/compiler/symbol/symtab_test.go b/internal/runtime/compiler/symbol/symtab_test.go
index 5d5eee93d..47fa7bb87 100644
--- a/internal/runtime/compiler/symbol/symtab_test.go
+++ b/internal/runtime/compiler/symbol/symtab_test.go
@@ -9,7 +9,10 @@ import (
"testing"
"testing/quick"
- "github.com/google/mtail/internal/testutil"
+ "github.com/google/go-cmp/cmp"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/errors"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler/position"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestInsertLookup(t *testing.T) {
@@ -76,3 +79,22 @@ func TestNestedScope(t *testing.T) {
t.Errorf("bar not found from s1")
}
}
+
+func TestCheck(t *testing.T) {
+ s := NewScope(nil)
+
+ pos := &position.Position{Filename: "test", Line: 1, Startcol: 1, Endcol: 3}
+
+ sym := NewSymbol("foo", VarSymbol, pos)
+ s.Insert(sym)
+
+ var errs errors.ErrorList
+ s.Check(&errs)
+
+ var wantErrs errors.ErrorList
+ wantErrs.Add(pos, "Declaration of variable `foo' here is never used.")
+ if diff := cmp.Diff(wantErrs, errs); diff != "" {
+ t.Errorf("Check() unexpected error diff (-want +got):\n%s", diff)
+ }
+
+}
diff --git a/internal/runtime/compiler/types/BUILD.bazel b/internal/runtime/compiler/types/BUILD.bazel
new file mode 100644
index 000000000..9affd3624
--- /dev/null
+++ b/internal/runtime/compiler/types/BUILD.bazel
@@ -0,0 +1,20 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "types",
+ srcs = [
+ "regexp.go",
+ "types.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/compiler/types",
+ visibility = ["//:__subpackages__"],
+ deps = ["@com_github_golang_glog//:glog"],
+)
+
+go_test(
+ name = "types_test",
+ size = "small",
+ srcs = ["types_test.go"],
+ embed = [":types"],
+ deps = ["//internal/testutil"],
+)
diff --git a/internal/runtime/compiler/types/types.go b/internal/runtime/compiler/types/types.go
index 1aef388b8..4d38d1367 100644
--- a/internal/runtime/compiler/types/types.go
+++ b/internal/runtime/compiler/types/types.go
@@ -60,7 +60,7 @@ func (e *TypeError) String() string {
return fmt.Sprintf("%s; expected %s received %s", e.error, estr, rstr)
}
-func (e TypeError) Error() string {
+func (e *TypeError) Error() string {
return e.String()
}
@@ -243,6 +243,8 @@ var (
Float = &Operator{"Float", []Type{}}
String = &Operator{"String", []Type{}}
Pattern = &Operator{"Pattern", []Type{}}
+ // LogFilter represents a type for the LOGFILTER construct.
+ LogFilter = &Operator{"LogFilter", []Type{String}}
// TODO(jaq): use composite type so we can typecheck the bucket directly, e.g. hist[j] = i.
Buckets = &Operator{"Buckets", []Type{}}
@@ -254,6 +256,7 @@ var (
var Builtins = map[string]Type{
"int": Function(NewVariable(), Int),
"bool": Function(NewVariable(), Bool),
+ "defined": Function(NewVariable(), Bool),
"float": Function(NewVariable(), Float),
"string": Function(NewVariable(), String),
"timestamp": Function(Int),
@@ -264,6 +267,7 @@ var Builtins = map[string]Type{
"tolower": Function(String, String),
"getfilename": Function(String),
"subst": Function(Pattern, String, String, String),
+ "log_filter": Function(String, LogFilter),
}
// FreshType returns a new type from the provided type scheme, replacing any
diff --git a/internal/runtime/compiler/types/types_test.go b/internal/runtime/compiler/types/types_test.go
index 92bd49a3c..ff61b05f8 100644
--- a/internal/runtime/compiler/types/types_test.go
+++ b/internal/runtime/compiler/types/types_test.go
@@ -8,7 +8,7 @@ import (
"fmt"
"testing"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var typeUnificationTests = []struct {
diff --git a/internal/runtime/fuzz.go b/internal/runtime/fuzz.go
index 926ddec98..75f839e44 100644
--- a/internal/runtime/fuzz.go
+++ b/internal/runtime/fuzz.go
@@ -12,9 +12,9 @@ import (
"flag"
"fmt"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/runtime/compiler"
- "github.com/google/mtail/internal/runtime/vm"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler"
+ "github.com/jaqx0r/mtail/internal/runtime/vm"
)
// U+2424 SYMBOL FOR NEWLINE
diff --git a/internal/runtime/httpstatus.go b/internal/runtime/httpstatus.go
index 5548f83f1..64902729e 100644
--- a/internal/runtime/httpstatus.go
+++ b/internal/runtime/httpstatus.go
@@ -9,7 +9,7 @@ import (
"io"
"net/http"
- "github.com/google/mtail/internal/runtime/vm"
+ "github.com/jaqx0r/mtail/internal/runtime/vm"
)
const loaderTemplate = `
diff --git a/internal/runtime/options.go b/internal/runtime/options.go
index f3ee353bf..2a1fae6dd 100644
--- a/internal/runtime/options.go
+++ b/internal/runtime/options.go
@@ -6,8 +6,8 @@ package runtime
import (
"time"
- "github.com/google/mtail/internal/runtime/compiler"
- "github.com/google/mtail/internal/runtime/vm"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler"
+ "github.com/jaqx0r/mtail/internal/runtime/vm"
"github.com/prometheus/client_golang/prometheus"
)
diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go
index 128137b71..99ca1bb21 100644
--- a/internal/runtime/runtime.go
+++ b/internal/runtime/runtime.go
@@ -20,10 +20,10 @@ import (
"time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/runtime/compiler"
- "github.com/google/mtail/internal/runtime/vm"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/runtime/compiler"
+ "github.com/jaqx0r/mtail/internal/runtime/vm"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
)
@@ -31,6 +31,8 @@ import (
var (
// LineCount counts the number of lines received by the program loader.
LineCount = expvar.NewInt("lines_total")
+ // ProgLinesCount counts the number of lines read by a program
+ ProgLinesCount = expvar.NewMap("prog_lines_total")
// ProgLoads counts the number of program load events.
ProgLoads = expvar.NewMap("prog_loads_total")
// ProgUnloads counts the number of program unload events.
@@ -170,16 +172,23 @@ func (r *Runtime) CompileAndRun(name string, input io.Reader) error {
glog.Info("Dumping program objects and bytecode\n", v.DumpByteCode())
}
+ r.logmappingsMu.RLock()
+ r.logmappings[name] = map[uint32]struct{}{}
+
+ for _, log := range obj.LogRestriction {
+ r.logmappings[name][logline.GetHash(log)] = struct{}{}
+ }
+
+ r.logmappingsMu.RUnlock()
+
// Load the metrics from the compilation into the global metric storage for export.
for _, m := range v.Metrics {
- if !m.Hidden {
- if r.omitMetricSource {
- m.Source = ""
- }
- err := r.ms.Add(m)
- if err != nil {
- return err
- }
+ if r.omitMetricSource {
+ m.Source = ""
+ }
+ err := r.ms.Add(m)
+ if err != nil {
+ return err
}
}
@@ -226,6 +235,9 @@ type Runtime struct {
handleMu sync.RWMutex // guards accesses to handles
handles map[string]*vmHandle // map of program names to virtual machines
+ logmappingsMu sync.RWMutex // guards access to logmappings
+ logmappings map[string]map[uint32]struct{} // logmappings is a map of hashed log names against the programs they apply to
+
programErrorMu sync.RWMutex // guards access to programErrors
programErrors map[string]error // errors from the last compile attempt of the program
@@ -259,6 +271,7 @@ func New(lines <-chan *logline.LogLine, wg *sync.WaitGroup, programPath string,
programPath: programPath,
handles: make(map[string]*vmHandle),
programErrors: make(map[string]error),
+ logmappings: make(map[string]map[uint32]struct{}),
signalQuit: make(chan struct{}),
}
initDone := make(chan struct{})
@@ -287,9 +300,14 @@ func New(lines <-chan *logline.LogLine, wg *sync.WaitGroup, programPath string,
for line := range lines {
LineCount.Add(1)
r.handleMu.RLock()
+ r.logmappingsMu.RLock()
for prog := range r.handles {
- r.handles[prog].lines <- line
+ if _, ok := r.logmappings[prog][line.Filenamehash]; ok || len(r.logmappings[prog]) == 0 {
+ ProgLinesCount.Add(prog, 1)
+ r.handles[prog].lines <- line
+ }
}
+ r.logmappingsMu.RUnlock()
r.handleMu.RUnlock()
}
glog.Info("END OF LINE")
diff --git a/internal/runtime/runtime_integration_test.go b/internal/runtime/runtime_integration_test.go
index f5b8b28b2..31d19d5d1 100644
--- a/internal/runtime/runtime_integration_test.go
+++ b/internal/runtime/runtime_integration_test.go
@@ -11,10 +11,10 @@ import (
"sync"
"testing"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var vmTests = []struct {
@@ -257,6 +257,35 @@ test -
},
},
},
+ {
+ "defined capture group",
+ `counter total
+/^[a-z]+ ((?P\d+)|-)$/ {
+ defined($response_size) {
+ total = $response_size
+ }
+}`,
+ `test 99
+test -
+`,
+ 0,
+ metrics.MetricSlice{
+ {
+ Name: "total",
+ Program: "defined capture group",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ Keys: []string{},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Value: &datum.Int{
+ Value: 99,
+ },
+ },
+ },
+ },
+ },
+ },
{
"add_assign_float",
`gauge metric
@@ -1072,6 +1101,160 @@ N && 1 {
errs: 0,
metrics: nil,
},
+ {
+ name: "const with id concat pattern",
+ prog: `counter c
+const GREET /hello/
+const SEP / /
+const PUNCT /world/
+const FULL GREET + SEP + PUNCT
+FULL {
+ c++
+}
+`,
+ log: `hello world
+other
+hello world
+`,
+ errs: 0,
+ metrics: metrics.MetricSlice{
+ {
+ Name: "c",
+ Program: "const with id concat pattern",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ Keys: []string{},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Value: &datum.Int{
+ Value: 2,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "const pattern as match condition with named capref",
+ prog: `counter c
+const A /(?Pn)/
+A {
+ c++
+}
+`,
+ log: `n
+x
+n
+`,
+ errs: 0,
+ metrics: metrics.MetricSlice{
+ {
+ Name: "c",
+ Program: "const pattern as match condition with named capref",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ Keys: []string{},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Value: &datum.Int{
+ Value: 2,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "const pattern as match condition simple",
+ prog: `counter c
+const A /n/
+A {
+ c++
+}
+`,
+ log: `n
+x
+n
+`,
+ errs: 0,
+ metrics: metrics.MetricSlice{
+ {
+ Name: "c",
+ Program: "const pattern as match condition simple",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ Keys: []string{},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Value: &datum.Int{
+ Value: 2,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "concat start match",
+ prog: `counter c
+const X /foo/
+/(?P.*)/ {
+ $line =~ X + /bar/ {
+ c++
+ }
+}
+`,
+ log: `foobar
+baz
+`,
+ errs: 0,
+ metrics: metrics.MetricSlice{
+ {
+ Name: "c",
+ Program: "concat start match",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ Keys: []string{},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Value: &datum.Int{
+ Value: 1,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "chained match capref",
+ prog: `counter c
+const PAT /n/
+/(\w+)/ && PAT {
+ c++
+}
+`,
+ log: `n
+x
+n
+`,
+ errs: 0,
+ metrics: metrics.MetricSlice{
+ {
+ Name: "c",
+ Program: "chained match capref",
+ Kind: metrics.Counter,
+ Type: metrics.Int,
+ Keys: []string{},
+ LabelValues: []*metrics.LabelValue{
+ {
+ Value: &datum.Int{
+ Value: 2,
+ },
+ },
+ },
+ },
+ },
+ },
}
func TestRuntimeEndToEnd(t *testing.T) {
@@ -1095,7 +1278,7 @@ func TestRuntimeEndToEnd(t *testing.T) {
lineCount := 0
for scanner.Scan() {
lineCount++
- lines <- logline.New(context.Background(), tc.name, scanner.Text())
+ lines <- logline.New(context.Background(), tc.name, logline.GetHash(tc.name), scanner.Text())
}
close(lines)
wg.Wait()
@@ -1104,6 +1287,9 @@ func TestRuntimeEndToEnd(t *testing.T) {
var ms metrics.MetricSlice
store.Range(func(m *metrics.Metric) error {
+ if m.Hidden {
+ return nil
+ }
ms = append(ms, m)
return nil
})
diff --git a/internal/runtime/runtime_test.go b/internal/runtime/runtime_test.go
index 32f6d5671..f9dc80338 100644
--- a/internal/runtime/runtime_test.go
+++ b/internal/runtime/runtime_test.go
@@ -10,9 +10,9 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestNewRuntime(t *testing.T) {
@@ -93,3 +93,125 @@ func TestLoadProg(t *testing.T) {
close(lines)
wg.Wait()
}
+
+func TestLogLineFilter(t *testing.T) {
+
+ tests := []struct {
+ lines []*logline.LogLine
+ logmappings map[uint32]struct{}
+ expected []*logline.LogLine
+ }{
+ {
+ // Test case where one file is processed and one not.
+ lines: []*logline.LogLine{
+ {
+ Filenamehash: 12345,
+ Line: "This is a valid log line",
+ },
+ {
+ Filenamehash: 67890,
+ Line: "This log line should be ignored",
+ },
+ },
+ expected: []*logline.LogLine{
+ {
+ Filenamehash: 12345,
+ Line: "This is a valid log line",
+ },
+ },
+ logmappings: map[uint32]struct{}{
+ 12345: {}, // This maps to the first line.
+ },
+ },
+ {
+ // Test case where both file are processed.
+ lines: []*logline.LogLine{
+ {
+ Filenamehash: 12345,
+ Line: "This is a valid log line",
+ },
+ {
+ Filenamehash: 67890,
+ Line: "This is a valid log line",
+ },
+ },
+ expected: []*logline.LogLine{
+ {
+ Filenamehash: 12345,
+ Line: "This is a valid log line",
+ },
+ {
+ Filenamehash: 67890,
+ Line: "This is a valid log line",
+ },
+ },
+ logmappings: map[uint32]struct{}{
+ 12345: {}, // This maps to the first line.
+ 67890: {}, // This maps to the first line.
+ },
+ },
+ {
+ // Test case where file process because no mapping.
+ lines: []*logline.LogLine{
+ {
+ Filenamehash: 12345,
+ Line: "This is a valid log line",
+ },
+ },
+ expected: []*logline.LogLine{
+ {
+ Filenamehash: 12345,
+ Line: "This is a valid log line",
+ },
+ },
+ logmappings: map[uint32]struct{}{}, // empty to all logs match
+ },
+ {
+ // empty test case
+ lines: []*logline.LogLine{},
+ expected: []*logline.LogLine{},
+ logmappings: map[uint32]struct{}{}, // empty to all logs match
+ },
+ }
+
+ for _, tc := range tests {
+ // Create a channel for log lines.
+ lines := make(chan *logline.LogLine, len(tc.lines))
+ for _, line := range tc.lines {
+ lines <- line
+ }
+ close(lines)
+
+ var wg sync.WaitGroup
+
+ store := metrics.NewStore()
+ // Create a Runtime instance with a logmapping for the first line.
+ r, err := New(lines, &wg, "", store)
+ testutil.FatalIfErr(t, err)
+
+ // Add a logmapping for the first line.
+ r.logmappings["test_program"] = tc.logmappings
+
+ // Add a mock program handle for "test_program".
+ linesReceived := make(chan *logline.LogLine, len(tc.expected))
+
+ // Start processing lines.
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for line := range lines {
+ if _, ok := r.logmappings["test_program"][line.Filenamehash]; ok {
+ linesReceived <- line
+ }
+ }
+ }()
+
+ // Wait for the Runtime to finish processing.
+ wg.Wait()
+
+ // Validate the lines received by the "test_program" handle.
+
+ testutil.ExpectLinesReceivedNoDiff(t, tc.expected, linesReceived)
+ }
+
+}
diff --git a/internal/runtime/vm/BUILD.bazel b/internal/runtime/vm/BUILD.bazel
new file mode 100644
index 000000000..dcba024ec
--- /dev/null
+++ b/internal/runtime/vm/BUILD.bazel
@@ -0,0 +1,32 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "vm",
+ srcs = ["vm.go"],
+ importpath = "github.com/jaqx0r/mtail/internal/runtime/vm",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/logline",
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/runtime/code",
+ "@com_github_golang_glog//:glog",
+ "@com_github_golang_groupcache//lru",
+ "@com_github_pkg_errors//:errors",
+ "@com_github_prometheus_client_golang//prometheus",
+ ],
+)
+
+go_test(
+ name = "vm_test",
+ size = "small",
+ srcs = ["vm_test.go"],
+ embed = [":vm"],
+ deps = [
+ "//internal/logline",
+ "//internal/metrics",
+ "//internal/metrics/datum",
+ "//internal/runtime/code",
+ "//internal/testutil",
+ ],
+)
diff --git a/internal/runtime/vm/vm.go b/internal/runtime/vm/vm.go
index 47492bfcf..37e4bd5bd 100644
--- a/internal/runtime/vm/vm.go
+++ b/internal/runtime/vm/vm.go
@@ -21,10 +21,10 @@ import (
"github.com/golang/glog"
"github.com/golang/groupcache/lru"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/runtime/code"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/runtime/code"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
)
@@ -41,12 +41,24 @@ var (
}, []string{"prog"})
)
+type matchResult struct {
+ text string
+ indices []int
+}
+
+func (m matchResult) captureGroup(n int) string {
+ if m.indices[2*n] == -1 {
+ return ""
+ }
+ return m.text[m.indices[2*n]:m.indices[2*n+1]]
+}
+
type thread struct {
- pc int // Program counter.
- matched bool // Flag set if any match has been found.
- matches map[int][]string // Match result variables.
- time time.Time // Time register.
- stack []interface{} // Data stack.
+ pc int // Program counter.
+ matched bool // Flag set if any match has been found.
+ matches map[int]matchResult // Match result variables, accessed as text[indices[n]:indices[n+1]].
+ time time.Time // Time register.
+ stack []interface{} // Data stack.
}
// VM describes the virtual machine for each program. It contains virtual
@@ -63,6 +75,8 @@ type VM struct {
timeMemos *lru.Cache // memo of time string parse results
+ threadPool sync.Pool // pool of re-used thread structs
+
t *thread // Current thread of execution
input *logline.LogLine // Log line input to this round of execution.
@@ -358,8 +372,11 @@ func (v *VM) execute(t *thread, i code.Instr) {
// Store the results in the operandth element of the stack,
// where i.opnd == the matched re index
index := i.Operand.(int)
- t.matches[index] = v.re[index].FindStringSubmatch(v.input.Line)
- t.Push(t.matches[index] != nil)
+ t.matches[index] = matchResult{
+ text: v.input.Line,
+ indices: v.re[index].FindStringSubmatchIndex(v.input.Line),
+ }
+ t.Push(t.matches[index].indices != nil)
case code.Smatch:
// match regex against item on the stack
@@ -369,8 +386,11 @@ func (v *VM) execute(t *thread, i code.Instr) {
v.errorf("+%v", err)
return
}
- t.matches[index] = v.re[index].FindStringSubmatch(line)
- t.Push(t.matches[index] != nil)
+ t.matches[index] = matchResult{
+ text: line,
+ indices: v.re[index].FindStringSubmatchIndex(line),
+ }
+ t.Push(t.matches[index].indices != nil)
case code.Cmp:
// Compare two elements on the stack.
@@ -578,7 +598,8 @@ func (v *VM) execute(t *thread, i code.Instr) {
}
re := int(val)
// Store the result from the re'th index at the s'th index
- ts = t.matches[re][s]
+ m := t.matches[re]
+ ts = m.captureGroup(s)
}
if cached, ok := v.timeMemos.Get(ts); !ok {
tm := v.ParseTime(layout, ts)
@@ -622,11 +643,16 @@ func (v *VM) execute(t *thread, i code.Instr) {
v.errorf("Invalid operand %v, not an int", i.Operand)
return
}
- if len(t.matches[re]) <= op {
- v.errorf("Not enough capture groups matched from %v to select %dth", t.matches[re], op)
+ m, ok := t.matches[re]
+ if !ok {
+ v.errorf("No match result for regex index %d", re)
+ return
+ }
+ if len(m.indices) < 2*(op+1) {
+ v.errorf("Not enough capture groups matched from %d indices to select %dth", len(m.indices)/2, op)
return
}
- t.Push(t.matches[re][op])
+ t.Push(m.captureGroup(op))
case code.Str:
// Put a string constant onto the stack
@@ -748,7 +774,7 @@ func (v *VM) execute(t *thread, i code.Instr) {
return
}
// fmt.Printf("s: %v\n", s)
- keys[a] = s
+ keys[a] = strings.Clone(s)
// fmt.Printf("Keys: %v\n", keys)
}
// fmt.Printf("Keys: %v\n", keys)
@@ -829,6 +855,32 @@ func (v *VM) execute(t *thread, i code.Instr) {
}
t.Push(len(s))
+ case code.Defined:
+ // Check if a capture group is defined (was matched) in the current match.
+ val := t.Pop()
+ re, ok := val.(int)
+ if !ok {
+ v.errorf("Invalid re index %v, not an int", val)
+ return
+ }
+ op, ok := i.Operand.(int)
+ if !ok {
+ v.errorf("Invalid operand %v, not an int", i.Operand)
+ return
+ }
+ m, ok := t.matches[re]
+ if !ok {
+ v.errorf("No match result for regex index %d", re)
+ return
+ }
+ if len(m.indices) >= 2*(op+1) && m.indices[2*op] != -1 {
+ t.matched = true
+ t.Push(true)
+ } else {
+ t.matched = false
+ t.Push(false)
+ }
+
case code.S2i:
base := 10
var err error
@@ -964,24 +1016,33 @@ func (v *VM) ProcessLogLine(_ context.Context, line *logline.LogLine) {
defer func() {
LineProcessingDurations.WithLabelValues(v.name).Observe(time.Since(start).Seconds())
}()
- t := new(thread)
- t.matched = false
- v.t = t
+ defer func() {
+ v.input = nil
+ if v.t != nil {
+ v.t.pc = 0
+ v.t.matched = false
+ v.t.time = time.Time{}
+ v.t.stack = v.t.stack[:0]
+ for k := range v.t.matches {
+ delete(v.t.matches, k)
+ }
+ v.threadPool.Put(v.t)
+ v.t = nil
+ }
+ }()
+ v.t = v.threadPool.Get().(*thread)
v.input = line
- t.stack = make([]interface{}, 0)
- t.matches = make(map[int][]string, len(v.re))
for {
- if t.pc >= len(v.prog) {
+ if v.t.pc >= len(v.prog) {
return
}
if v.trace != nil {
- v.trace = append(v.trace, t.pc)
+ v.trace = append(v.trace, v.t.pc)
}
- i := v.prog[t.pc]
- t.pc++
- v.execute(t, i)
+ i := v.prog[v.t.pc]
+ v.t.pc++
+ v.execute(v.t, i)
if v.terminate {
- // Terminate only stops this invocation on this line of input; reset the terminate flag.
v.terminate = false
return
}
@@ -1001,6 +1062,14 @@ func New(name string, obj *code.Object, syslogUseCurrentYear bool, loc *time.Loc
syslogUseCurrentYear: syslogUseCurrentYear,
loc: loc,
logRuntimeErrors: log,
+ threadPool: sync.Pool{
+ New: func() any {
+ return &thread{
+ matches: make(map[int]matchResult, len(obj.Regexps)),
+ stack: make([]interface{}, 0),
+ }
+ },
+ },
}
if trace {
v.trace = make([]int, 0, len(v.prog))
diff --git a/internal/runtime/vm/vm_test.go b/internal/runtime/vm/vm_test.go
index 98c78caa0..00c52324f 100644
--- a/internal/runtime/vm/vm_test.go
+++ b/internal/runtime/vm/vm_test.go
@@ -6,14 +6,17 @@ package vm
import (
"context"
"regexp"
+ "runtime"
+ "strings"
"testing"
"time"
+ "unsafe"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/metrics"
- "github.com/google/mtail/internal/metrics/datum"
- "github.com/google/mtail/internal/runtime/code"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/metrics"
+ "github.com/jaqx0r/mtail/internal/metrics/datum"
+ "github.com/jaqx0r/mtail/internal/runtime/code"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
var instructions = []struct {
@@ -28,564 +31,564 @@ var instructions = []struct {
}{
{
"match",
- code.Instr{code.Match, 0, 0},
+ code.Instr{Opcode: code.Match, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{regexp.MustCompile("a*b")},
[]string{},
[]interface{}{},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{0: {"aaaab"}}},
+ thread{pc: 0, matches: map[int]matchResult{0: {text: "aaaab", indices: []int{0, 5}}}},
},
{
"cmp lt",
- code.Instr{code.Cmp, -1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: -1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1, "2"},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp eq",
- code.Instr{code.Cmp, 0, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"2", "2"},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp le",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, "2"},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp ne",
- code.Instr{code.Cmp, 0, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"1", "2"},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp ge",
- code.Instr{code.Cmp, -1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: -1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 2},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt float float",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"2.0", "1.0"},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt float int",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"1.0", "2"},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt int float",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"1", "2.0"},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp eq string string false",
- code.Instr{code.Cmp, 0, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"abc", "def"},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp eq string string true",
- code.Instr{code.Cmp, 0, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"abc", "abc"},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt float float",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2.0, 1.0},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt float int",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cmp gt int float",
- code.Instr{code.Cmp, 1, 0},
+ code.Instr{Opcode: code.Cmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1, 2.0},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"jnm",
- code.Instr{code.Jnm, 37, 0},
+ code.Instr{Opcode: code.Jnm, Operand: 37, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{false},
[]interface{}{},
- thread{pc: 37, matches: map[int][]string{}},
+ thread{pc: 37, matches: map[int]matchResult{}},
},
{
"jm",
- code.Instr{code.Jm, 37, 0},
+ code.Instr{Opcode: code.Jm, Operand: 37, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{false},
[]interface{}{},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"jmp",
- code.Instr{code.Jmp, 37, 0},
+ code.Instr{Opcode: code.Jmp, Operand: 37, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{},
- thread{pc: 37, matches: map[int][]string{}},
+ thread{pc: 37, matches: map[int]matchResult{}},
},
{
"strptime",
- code.Instr{code.Strptime, 0, 0},
+ code.Instr{Opcode: code.Strptime, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"2012/01/18 06:25:00", "2006/01/02 15:04:05"},
[]interface{}{},
thread{
pc: 0, time: time.Date(2012, 1, 18, 6, 25, 0, 0, time.UTC),
- matches: map[int][]string{},
+ matches: map[int]matchResult{},
},
},
{
"iadd",
- code.Instr{code.Iadd, 0, 0},
+ code.Instr{Opcode: code.Iadd, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(3)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"isub",
- code.Instr{code.Isub, 0, 0},
+ code.Instr{Opcode: code.Isub, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(1)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"imul",
- code.Instr{code.Imul, 0, 0},
+ code.Instr{Opcode: code.Imul, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(2)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"idiv",
- code.Instr{code.Idiv, 0, 0},
+ code.Instr{Opcode: code.Idiv, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{4, 2},
[]interface{}{int64(2)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"imod",
- code.Instr{code.Imod, 0, 0},
+ code.Instr{Opcode: code.Imod, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{4, 2},
[]interface{}{int64(0)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"imod 2",
- code.Instr{code.Imod, 0, 0},
+ code.Instr{Opcode: code.Imod, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{3, 2},
[]interface{}{int64(1)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"tolower",
- code.Instr{code.Tolower, 0, 0},
+ code.Instr{Opcode: code.Tolower, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"mIxeDCasE"},
[]interface{}{"mixedcase"},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"length",
- code.Instr{code.Length, 0, 0},
+ code.Instr{Opcode: code.Length, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"1234"},
[]interface{}{4},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"length 0",
- code.Instr{code.Length, 0, 0},
+ code.Instr{Opcode: code.Length, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{""},
[]interface{}{0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"shl",
- code.Instr{code.Shl, 0, 0},
+ code.Instr{Opcode: code.Shl, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(4)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"shr",
- code.Instr{code.Shr, 0, 0},
+ code.Instr{Opcode: code.Shr, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(1)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"and",
- code.Instr{code.And, 0, 0},
+ code.Instr{Opcode: code.And, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(0)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"or",
- code.Instr{code.Or, 0, 0},
+ code.Instr{Opcode: code.Or, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(3)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"xor",
- code.Instr{code.Xor, 0, 0},
+ code.Instr{Opcode: code.Xor, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 1},
[]interface{}{int64(3)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"xor 2",
- code.Instr{code.Xor, 0, 0},
+ code.Instr{Opcode: code.Xor, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 3},
[]interface{}{int64(1)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"xor 3",
- code.Instr{code.Xor, 0, 0},
+ code.Instr{Opcode: code.Xor, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{-1, 3},
[]interface{}{int64(^3)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"neg",
- code.Instr{code.Neg, 0, 0},
+ code.Instr{Opcode: code.Neg, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{0},
[]interface{}{int64(-1)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"not",
- code.Instr{code.Not, 0, 0},
+ code.Instr{Opcode: code.Not, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{false},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"pow",
- code.Instr{code.Ipow, 0, 0},
+ code.Instr{Opcode: code.Ipow, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2, 2},
[]interface{}{int64(4)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"s2i pop",
- code.Instr{code.S2i, 1, 0},
+ code.Instr{Opcode: code.S2i, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"ff", 16},
[]interface{}{int64(255)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"s2i",
- code.Instr{code.S2i, nil, 0},
+ code.Instr{Opcode: code.S2i, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"190"},
[]interface{}{int64(190)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"s2f",
- code.Instr{code.S2f, nil, 0},
+ code.Instr{Opcode: code.S2f, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"1.0"},
[]interface{}{float64(1.0)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"i2f",
- code.Instr{code.I2f, nil, 0},
+ code.Instr{Opcode: code.I2f, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1},
[]interface{}{float64(1.0)},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"settime",
- code.Instr{code.Settime, 0, 0},
+ code.Instr{Opcode: code.Settime, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{int64(0)},
[]interface{}{},
- thread{pc: 0, time: time.Unix(0, 0).UTC(), matches: map[int][]string{}},
+ thread{pc: 0, time: time.Unix(0, 0).UTC(), matches: map[int]matchResult{}},
},
{
"push int",
- code.Instr{code.Push, 1, 0},
+ code.Instr{Opcode: code.Push, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{1},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"push float",
- code.Instr{code.Push, 1.0, 0},
+ code.Instr{Opcode: code.Push, Operand: 1.0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{1.0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"setmatched false",
- code.Instr{code.Setmatched, false, 0},
+ code.Instr{Opcode: code.Setmatched, Operand: false, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{},
- thread{matched: false, pc: 0, matches: map[int][]string{}},
+ thread{matched: false, pc: 0, matches: map[int]matchResult{}},
},
{
"setmatched true",
- code.Instr{code.Setmatched, true, 0},
+ code.Instr{Opcode: code.Setmatched, Operand: true, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{},
- thread{matched: true, pc: 0, matches: map[int][]string{}},
+ thread{matched: true, pc: 0, matches: map[int]matchResult{}},
},
{
"otherwise",
- code.Instr{code.Otherwise, nil, 0},
+ code.Instr{Opcode: code.Otherwise, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{true},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fadd",
- code.Instr{code.Fadd, nil, 0},
+ code.Instr{Opcode: code.Fadd, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2.0},
[]interface{}{3.0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fsub",
- code.Instr{code.Fsub, nil, 0},
+ code.Instr{Opcode: code.Fsub, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2.0},
[]interface{}{-1.0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fmul",
- code.Instr{code.Fmul, nil, 0},
+ code.Instr{Opcode: code.Fmul, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2.0},
[]interface{}{2.0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fdiv",
- code.Instr{code.Fdiv, nil, 0},
+ code.Instr{Opcode: code.Fdiv, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2.0},
[]interface{}{0.5},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fmod",
- code.Instr{code.Fmod, nil, 0},
+ code.Instr{Opcode: code.Fmod, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2.0},
[]interface{}{1.0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fpow",
- code.Instr{code.Fpow, nil, 0},
+ code.Instr{Opcode: code.Fpow, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{2.0, 2.0},
[]interface{}{4.0},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"getfilename",
- code.Instr{code.Getfilename, nil, 0},
+ code.Instr{Opcode: code.Getfilename, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{},
[]interface{}{testFilename},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"i2s",
- code.Instr{code.I2s, nil, 0},
+ code.Instr{Opcode: code.I2s, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1},
[]interface{}{"1"},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"f2s",
- code.Instr{code.F2s, nil, 0},
+ code.Instr{Opcode: code.F2s, Operand: nil, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{3.1},
[]interface{}{"3.1"},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"cat",
- code.Instr{code.Cat, 0, 0},
+ code.Instr{Opcode: code.Cat, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"first", "second"},
[]interface{}{"firstsecond"},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"icmp gt false",
- code.Instr{code.Icmp, 1, 0},
+ code.Instr{Opcode: code.Icmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1, 2},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"fcmp gt false",
- code.Instr{code.Fcmp, 1, 0},
+ code.Instr{Opcode: code.Fcmp, Operand: 1, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{1.0, 2.0},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"scmp eq false",
- code.Instr{code.Scmp, 0, 0},
+ code.Instr{Opcode: code.Scmp, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"abc", "def"},
[]interface{}{false},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
{
"subst",
- code.Instr{code.Subst, 0, 0},
+ code.Instr{Opcode: code.Subst, Operand: 0, SourceLine: 0},
[]*regexp.Regexp{},
[]string{},
[]interface{}{"aa" /*old*/, "a" /*new*/, "caat"},
[]interface{}{"cat"},
- thread{pc: 0, matches: map[int][]string{}},
+ thread{pc: 0, matches: map[int]matchResult{}},
},
}
@@ -609,8 +612,8 @@ func TestInstrs(t *testing.T) {
for _, item := range tc.reversedStack {
v.t.Push(item)
}
- v.t.matches = make(map[int][]string)
- v.input = logline.New(context.Background(), testFilename, "aaaab")
+ v.t.matches = make(map[int]matchResult)
+ v.input = logline.New(context.Background(), testFilename, logline.GetHash(testFilename), "aaaab")
v.execute(v.t, tc.i)
if v.terminate {
t.Fatalf("Execution failed, see info log.")
@@ -620,7 +623,7 @@ func TestInstrs(t *testing.T) {
tc.expectedThread.stack = tc.expectedStack
- testutil.ExpectNoDiff(t, &tc.expectedThread, v.t, testutil.AllowUnexported(thread{}))
+ testutil.ExpectNoDiff(t, &tc.expectedThread, v.t, testutil.AllowUnexported(thread{}), testutil.AllowUnexported(matchResult{}))
})
}
}
@@ -631,8 +634,8 @@ func makeVM(i code.Instr, m []*metrics.Metric) *VM {
v := New("test", obj, true, nil, false, false)
v.t = new(thread)
v.t.stack = make([]interface{}, 0)
- v.t.matches = make(map[int][]string)
- v.input = logline.New(context.Background(), testFilename, "aaaab")
+ v.t.matches = make(map[int]matchResult)
+ v.input = logline.New(context.Background(), testFilename, logline.GetHash(testFilename), "aaaab")
return v
}
@@ -661,7 +664,7 @@ func TestDatumSetInstrs(t *testing.T) {
tests := []datumStoreTests{
{
name: "simple inc",
- i: code.Instr{code.Inc, nil, 0},
+ i: code.Instr{Opcode: code.Inc, Operand: nil, SourceLine: 0},
d: 0,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -670,7 +673,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "inc by int",
- i: code.Instr{code.Inc, 0, 0},
+ i: code.Instr{Opcode: code.Inc, Operand: 0, SourceLine: 0},
d: 0,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -680,7 +683,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "inc by str",
- i: code.Instr{code.Inc, 0, 0},
+ i: code.Instr{Opcode: code.Inc, Operand: 0, SourceLine: 0},
d: 0,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -690,7 +693,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "iset",
- i: code.Instr{code.Iset, nil, 0},
+ i: code.Instr{Opcode: code.Iset, Operand: nil, SourceLine: 0},
d: 0,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -700,7 +703,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "iset str",
- i: code.Instr{code.Iset, nil, 0},
+ i: code.Instr{Opcode: code.Iset, Operand: nil, SourceLine: 0},
d: 0,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -710,7 +713,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "fset",
- i: code.Instr{code.Fset, nil, 0},
+ i: code.Instr{Opcode: code.Fset, Operand: nil, SourceLine: 0},
d: 1,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -720,7 +723,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "fset str",
- i: code.Instr{code.Fset, nil, 0},
+ i: code.Instr{Opcode: code.Fset, Operand: nil, SourceLine: 0},
d: 1,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -730,7 +733,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "sset",
- i: code.Instr{code.Sset, nil, 0},
+ i: code.Instr{Opcode: code.Sset, Operand: nil, SourceLine: 0},
d: 2,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -740,7 +743,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "dec",
- i: code.Instr{code.Dec, nil, 0},
+ i: code.Instr{Opcode: code.Dec, Operand: nil, SourceLine: 0},
d: 0,
setup: func(t *thread, d datum.Datum) {
datum.SetInt(d, 1, time.Now())
@@ -750,7 +753,7 @@ func TestDatumSetInstrs(t *testing.T) {
},
{
name: "set hist",
- i: code.Instr{code.Fset, nil, 0},
+ i: code.Instr{Opcode: code.Fset, Operand: nil, SourceLine: 0},
d: 3,
setup: func(t *thread, d datum.Datum) {
t.Push(d)
@@ -781,8 +784,11 @@ func TestDatumSetInstrs(t *testing.T) {
}
func TestStrptimeWithTimezone(t *testing.T) {
- loc, _ := time.LoadLocation("Europe/Berlin")
- obj := &code.Object{Program: []code.Instr{{code.Strptime, 0, 0}}}
+ loc, err := time.LoadLocation("Europe/Berlin")
+ if err != nil {
+ t.Skip("Skipping, timezone database not available:", err)
+ }
+ obj := &code.Object{Program: []code.Instr{{Opcode: code.Strptime, Operand: 0, SourceLine: 0}}}
vm := New("strptimezone", obj, true, loc, false, false)
vm.t = new(thread)
vm.t.stack = make([]interface{}, 0)
@@ -795,7 +801,7 @@ func TestStrptimeWithTimezone(t *testing.T) {
}
func TestStrptimeWithoutTimezone(t *testing.T) {
- obj := &code.Object{Program: []code.Instr{{code.Strptime, 0, 0}}}
+ obj := &code.Object{Program: []code.Instr{{Opcode: code.Strptime, Operand: 0, SourceLine: 0}}}
vm := New("strptimezone", obj, true, nil, false, false)
vm.t = new(thread)
vm.t.stack = make([]interface{}, 0)
@@ -817,7 +823,7 @@ func TestDatumFetchInstrs(t *testing.T) {
{
// iget
- v := makeVM(code.Instr{code.Iget, nil, 0}, m)
+ v := makeVM(code.Instr{Opcode: code.Iget, Operand: nil, SourceLine: 0}, m)
d, err := m[0].GetDatum()
testutil.FatalIfErr(t, err)
datum.SetInt(d, 37, time.Now())
@@ -837,7 +843,7 @@ func TestDatumFetchInstrs(t *testing.T) {
{
// fget
- v := makeVM(code.Instr{code.Fget, nil, 0}, m)
+ v := makeVM(code.Instr{Opcode: code.Fget, Operand: nil, SourceLine: 0}, m)
d, err := m[1].GetDatum()
testutil.FatalIfErr(t, err)
datum.SetFloat(d, 12.1, time.Now())
@@ -857,7 +863,7 @@ func TestDatumFetchInstrs(t *testing.T) {
{
// sget
- v := makeVM(code.Instr{code.Sget, nil, 0}, m)
+ v := makeVM(code.Instr{Opcode: code.Sget, Operand: nil, SourceLine: 0}, m)
d, err := m[2].GetDatum()
testutil.FatalIfErr(t, err)
datum.SetString(d, "aba", time.Now())
@@ -885,7 +891,7 @@ func TestDeleteInstrs(t *testing.T) {
_, err := m[0].GetDatum("z")
testutil.FatalIfErr(t, err)
- v := makeVM(code.Instr{code.Expire, 1, 0}, m)
+ v := makeVM(code.Instr{Opcode: code.Expire, Operand: 1, SourceLine: 0}, m)
v.t.Push(time.Hour)
v.t.Push("z")
v.t.Push(m[0])
@@ -905,7 +911,7 @@ func TestDeleteInstrs(t *testing.T) {
func TestTimestampInstr(t *testing.T) {
var m []*metrics.Metric
now := time.Now().UTC()
- v := makeVM(code.Instr{code.Timestamp, nil, 0}, m)
+ v := makeVM(code.Instr{Opcode: code.Timestamp, Operand: nil, SourceLine: 0}, m)
v.execute(v.t, v.prog[0])
if v.terminate {
t.Fatal("execution failed, see info log")
@@ -927,3 +933,71 @@ func TestTimestampInstr(t *testing.T) {
t.Errorf("Expecting timestamp to be %s, was %s", newT, tos)
}
}
+
+func TestProcessLogLineDoesNotPinLargeCaptureGroup(t *testing.T) {
+ // Build a program that matches a regex, captures a substring, and stores it
+ // as a metric label key via Dload. The stored key must not pin the original
+ // log line's backing array.
+ re := regexp.MustCompile(`.(KEY).`)
+
+ m := []*metrics.Metric{
+ metrics.NewMetric("m", "tst", metrics.Counter, metrics.Int, "label"),
+ }
+ prog := []code.Instr{
+ {Opcode: code.Match, Operand: 0, SourceLine: 0},
+ {Opcode: code.Push, Operand: 0, SourceLine: 0},
+ {Opcode: code.Capref, Operand: 1, SourceLine: 0},
+ {Opcode: code.Mload, Operand: 0, SourceLine: 0},
+ {Opcode: code.Dload, Operand: 1, SourceLine: 0},
+ }
+ obj := &code.Object{
+ Metrics: m,
+ Program: prog,
+ Regexps: []*regexp.Regexp{re},
+ }
+ v := New("leaktest", obj, true, nil, false, false)
+
+ // Allocate a large log line (~200KB). The regex `.(KEY).` matches
+ // "aKEYb" and captures "KEY". Save the data pointer of the capture to
+ // compare against the stored label value later.
+ const offset = 100000
+ large := strings.Repeat("x", offset) + "aKEYb" + strings.Repeat("y", 100000)
+ capture := large[offset+1 : offset+4] // "KEY" β shares backing with large
+ origPtr := unsafe.StringData(capture)
+
+ v.ProcessLogLine(context.Background(), logline.New(context.Background(), "test", 0, large))
+ runtime.KeepAlive(large) // ensure large survives until ProcessLogLine completes
+
+ // Retrieve the stored label value.
+ lv := m[0].FindLabelValueOrNil([]string{"KEY"})
+ if lv == nil {
+ t.Fatal("label value not found")
+ }
+ stored := lv.Labels[0]
+
+ // Drop all references to the large backing array. If strings.Clone was not
+ // used, the stored key still pins the original backing array via the shared
+ // data pointer.
+ large = ""
+ runtime.GC()
+
+ // If the stored key shares the original backing array, its data pointer
+ // matches. If strings.Clone allocated a fresh copy, they differ.
+ if unsafe.StringData(stored) == origPtr {
+ t.Error("stored label key shares backing array with original log line; Dload should use strings.Clone to detach it")
+ }
+}
+
+func TestProcessLogLineClearsInput(t *testing.T) {
+ obj := &code.Object{Program: []code.Instr{}} // empty program returns immediately
+ v := New("leaktest", obj, true, nil, false, false)
+ line := logline.New(context.Background(), "test", 0, "hello world")
+
+ v.ProcessLogLine(context.Background(), line)
+ if v.input != nil {
+ t.Error("v.input was not cleared after ProcessLogLine returned")
+ }
+ if v.t != nil {
+ t.Error("v.t was not cleared after ProcessLogLine returned")
+ }
+}
diff --git a/internal/tailer/BUILD.bazel b/internal/tailer/BUILD.bazel
new file mode 100644
index 000000000..061f02be9
--- /dev/null
+++ b/internal/tailer/BUILD.bazel
@@ -0,0 +1,69 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "tailer",
+ srcs = [
+ "httpstatus.go",
+ "tail.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/tailer",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/logline",
+ "//internal/tailer/logstream",
+ "//internal/waker",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "tailer_test",
+ size = "small",
+ srcs = [
+ "tail_test.go",
+ "tail_unix_test.go",
+ "tail_windows_test.go",
+ ],
+ embed = [":tailer"],
+ deps = [
+ "//internal/logline",
+ "//internal/testutil",
+ "//internal/waker",
+ "@com_github_golang_glog//:glog",
+ ] + select({
+ "@rules_go//go/platform:aix": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:android": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:darwin": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:dragonfly": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:freebsd": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:illumos": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:ios": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:linux": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:netbsd": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:openbsd": [
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:solaris": [
+ "@org_golang_x_sys//unix",
+ ],
+ "//conditions:default": [],
+ }),
+)
diff --git a/internal/tailer/httpstatus.go b/internal/tailer/httpstatus.go
index 7ef89fcca..75a7faab8 100644
--- a/internal/tailer/httpstatus.go
+++ b/internal/tailer/httpstatus.go
@@ -8,7 +8,7 @@ import (
"html/template"
"io"
- "github.com/google/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
)
const tailerTemplate = `
diff --git a/internal/tailer/logstream/BUILD.bazel b/internal/tailer/logstream/BUILD.bazel
new file mode 100644
index 000000000..115472391
--- /dev/null
+++ b/internal/tailer/logstream/BUILD.bazel
@@ -0,0 +1,93 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "logstream",
+ srcs = [
+ "base.go",
+ "cancel.go",
+ "dgramstream.go",
+ "fifostream.go",
+ "filestream.go",
+ "filestream_open_unix.go",
+ "filestream_open_windows.go",
+ "logstream.go",
+ "reader.go",
+ "socketstream.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/tailer/logstream",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/logline",
+ "//internal/waker",
+ "@com_github_golang_glog//:glog",
+ ],
+)
+
+go_test(
+ name = "logstream_test",
+ size = "small",
+ srcs = [
+ "dgramstream_unix_test.go",
+ "fifostream_unix_test.go",
+ "filestream_test.go",
+ "filestream_unix_test.go",
+ "logstream_test.go",
+ "logstream_unix_test.go",
+ "reader_test.go",
+ "socketstream_unix_test.go",
+ ],
+ embed = [":logstream"],
+ deps = [
+ "//internal/logline",
+ "//internal/testutil",
+ "//internal/waker",
+ "@com_github_google_go_cmp//cmp",
+ "@com_github_google_go_cmp//cmp/cmpopts",
+ ] + select({
+ "@rules_go//go/platform:aix": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:android": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:darwin": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:dragonfly": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:freebsd": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:illumos": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:ios": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:linux": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:netbsd": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:openbsd": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "@rules_go//go/platform:solaris": [
+ "@com_github_golang_glog//:glog",
+ "@org_golang_x_sys//unix",
+ ],
+ "//conditions:default": [],
+ }),
+)
diff --git a/internal/tailer/logstream/base.go b/internal/tailer/logstream/base.go
index 4188886f9..49e02db1b 100644
--- a/internal/tailer/logstream/base.go
+++ b/internal/tailer/logstream/base.go
@@ -4,7 +4,7 @@
package logstream
import (
- "github.com/google/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/logline"
)
type streamBase struct {
diff --git a/internal/tailer/logstream/dgramstream.go b/internal/tailer/logstream/dgramstream.go
index 12509b1a2..26826e869 100644
--- a/internal/tailer/logstream/dgramstream.go
+++ b/internal/tailer/logstream/dgramstream.go
@@ -10,8 +10,8 @@ import (
"sync"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/waker"
)
type dgramStream struct {
diff --git a/internal/tailer/logstream/dgramstream_unix_test.go b/internal/tailer/logstream/dgramstream_unix_test.go
index 0899dfe65..143624a86 100644
--- a/internal/tailer/logstream/dgramstream_unix_test.go
+++ b/internal/tailer/logstream/dgramstream_unix_test.go
@@ -14,10 +14,10 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
const dgramTimeout = 1 * time.Second
@@ -34,7 +34,7 @@ func TestDgramStreamReadCompletedBecauseSocketClosed(t *testing.T) {
tmpDir := testutil.TestTempDir(t)
addr = filepath.Join(tmpDir, "sock")
case "udp":
- addr = fmt.Sprintf("[::]:%d", testutil.FreePort(t))
+ addr = fmt.Sprintf("127.0.0.1:%d", testutil.FreePort(t))
default:
t.Fatalf("bad scheme %s", scheme)
}
@@ -49,7 +49,7 @@ func TestDgramStreamReadCompletedBecauseSocketClosed(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: sockName, Line: "1"},
+ {Context: context.TODO(), Filename: sockName, Line: "1", Filenamehash: logline.GetHash(sockName)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ds.Lines())
@@ -86,7 +86,7 @@ func TestDgramStreamReadCompletedBecauseCancel(t *testing.T) {
tmpDir := testutil.TestTempDir(t)
addr = filepath.Join(tmpDir, "sock")
case "udp":
- addr = fmt.Sprintf("[::]:%d", testutil.FreePort(t))
+ addr = fmt.Sprintf("127.0.0.1:%d", testutil.FreePort(t))
default:
t.Fatalf("bad scheme %s", scheme)
}
@@ -98,25 +98,22 @@ func TestDgramStreamReadCompletedBecauseCancel(t *testing.T) {
ds, err := logstream.New(ctx, &wg, waker, sockName, logstream.OneShotDisabled)
testutil.FatalIfErr(t, err)
- expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: sockName, Line: "1"},
- }
- checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ds.Lines())
-
s, err := net.Dial(scheme, addr)
testutil.FatalIfErr(t, err)
_, err = s.Write([]byte("1\n"))
testutil.FatalIfErr(t, err)
- // Yield to give the stream a chance to read.
- time.Sleep(10 * time.Millisecond)
+ // Read from Lines to synchronise with the stream goroutine: this
+ // blocks until the stream has consumed the data, proving it read
+ // "1\n" from the socket before we cancel.
+ expected := &logline.LogLine{Context: context.TODO(), Filename: sockName, Line: "1", Filenamehash: logline.GetHash(sockName)}
+ received := <-ds.Lines()
+ testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
cancel() // This cancellation should cause the stream to shut down.
wg.Wait()
- checkLineDiff()
-
if v := <-ds.Lines(); v != nil {
t.Errorf("expecting dgramstream to be complete because cancel")
}
diff --git a/internal/tailer/logstream/fifostream.go b/internal/tailer/logstream/fifostream.go
index 9917bb694..8c420de3d 100644
--- a/internal/tailer/logstream/fifostream.go
+++ b/internal/tailer/logstream/fifostream.go
@@ -12,8 +12,8 @@ import (
"syscall"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/waker"
)
type fifoStream struct {
diff --git a/internal/tailer/logstream/fifostream_unix_test.go b/internal/tailer/logstream/fifostream_unix_test.go
index 4d8272acc..72a586704 100644
--- a/internal/tailer/logstream/fifostream_unix_test.go
+++ b/internal/tailer/logstream/fifostream_unix_test.go
@@ -13,10 +13,10 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
"golang.org/x/sys/unix"
)
@@ -43,7 +43,7 @@ func TestFifoStreamReadCompletedBecauseClosed(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "1"},
+ {Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ps.Lines())
@@ -80,18 +80,19 @@ func TestFifoStreamReadCompletedBecauseCancel(t *testing.T) {
ps, err := logstream.New(ctx, &wg, waker, name, logstream.OneShotDisabled)
testutil.FatalIfErr(t, err)
- expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "1"},
- }
- checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ps.Lines())
testutil.WriteString(t, f, "1\n")
+ // Read from Lines to synchronise with the stream goroutine: this
+ // blocks until the stream has consumed the data, proving it read "1\n"
+ // from the fifo before we cancel.
+ expected := &logline.LogLine{Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)}
+ received := <-ps.Lines()
+ testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
+
cancel() // Cancellation here should cause the stream to shut down.
wg.Wait()
- checkLineDiff()
-
if v := <-ps.Lines(); v != nil {
t.Errorf("expecting pipestream to be complete because cancelled")
}
@@ -115,8 +116,8 @@ func TestFifoStreamReadURL(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "1"},
- {Context: context.TODO(), Filename: name, Line: "2"},
+ {Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)},
+ {Context: context.TODO(), Filename: name, Line: "2", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ps.Lines())
@@ -164,8 +165,8 @@ func TestFifoStreamReadStdin(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: "-", Line: "1"},
- {Context: context.TODO(), Filename: "-", Line: "2"},
+ {Context: context.TODO(), Filename: "-", Line: "1", Filenamehash: logline.GetHash("-")},
+ {Context: context.TODO(), Filename: "-", Line: "2", Filenamehash: logline.GetHash("-")},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ps.Lines())
diff --git a/internal/tailer/logstream/filestream.go b/internal/tailer/logstream/filestream.go
index f77b1adbf..f9e4b41c3 100644
--- a/internal/tailer/logstream/filestream.go
+++ b/internal/tailer/logstream/filestream.go
@@ -11,10 +11,11 @@ import (
"os"
"sync"
"syscall"
+ "time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/waker"
)
// fileTruncates counts the truncations of a file stream.
@@ -59,7 +60,7 @@ func newFileStream(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, p
}
func (fs *fileStream) stream(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, fi os.FileInfo, oneShot OneShotMode, streamFromStart bool) error {
- fd, err := os.OpenFile(fs.pathname, os.O_RDONLY, 0o600)
+ fd, err := openFile(fs.pathname)
if err != nil {
logErrors.Add(fs.sourcename, 1)
return err
@@ -113,16 +114,21 @@ func (fs *fileStream) stream(ctx context.Context, wg *sync.WaitGroup, waker wake
if err != nil && !errors.Is(err, io.EOF) {
logErrors.Add(fs.sourcename, 1)
- // TODO: This could be generalised to check for any retryable
- // errors, and end on unretriables; e.g. ESTALE looks
- // retryable.
if errors.Is(err, syscall.ESTALE) {
glog.Infof("stream(%s): reopening stream due to %s", fs.sourcename, err)
- // streamFromStart always true on a stream reopen
- if nerr := fs.stream(ctx, wg, waker, fi, oneShot, true); nerr != nil {
+ // Rate-limit ESTALE retries to prevent CPU thrashing
+ // on NFS when the stale handle condition persists.
+ time.Sleep(time.Second)
+ newfi, serr := os.Stat(fs.pathname)
+ if serr != nil {
+ glog.Infof("stream(%s): stat after ESTALE: %v", fs.sourcename, serr)
+ close(fs.lines)
+ return
+ }
+ if nerr := fs.stream(ctx, wg, waker, newfi, oneShot, true); nerr != nil {
glog.Infof("stream(%s): new stream: %v", fs.sourcename, nerr)
+ close(fs.lines)
}
- // Close this stream.
return
}
glog.Infof("stream(%s): read error: %v", fs.sourcename, err)
@@ -137,12 +143,12 @@ func (fs *fileStream) stream(ctx context.Context, wg *sync.WaitGroup, waker wake
newfi, serr := os.Stat(fs.pathname)
if serr != nil {
glog.Infof("stream(%s): stat error: %v", serr)
- // If this is a NotExist error, then we should wrap up this
- // goroutine. The Tailer will create a new logstream if the
- // file is in the middle of a rotation and gets recreated
- // in the next moment. We can't rely on the Tailer to tell
- // us we're deleted because the tailer can only tell us to
- // cancel.
+ if errors.Is(serr, syscall.ESTALE) {
+ glog.V(2).Infof("stream(%s): stale NFS handle on stat, exiting", fs.sourcename)
+ lr.Finish(ctx)
+ close(fs.lines)
+ return
+ }
if os.IsNotExist(serr) {
glog.V(2).Infof("stream(%s): source no longer exists, exiting", fs.sourcename)
lr.Finish(ctx)
@@ -157,6 +163,7 @@ func (fs *fileStream) stream(ctx context.Context, wg *sync.WaitGroup, waker wake
// Stream from start always true on a stream reopen
if err := fs.stream(ctx, wg, waker, newfi, oneShot, true); err != nil {
glog.Info("stream(%s): new stream: %v", fs.sourcename, err)
+ close(fs.lines)
}
// We're at EOF so there's nothing left to read here.
return
diff --git a/internal/tailer/logstream/filestream_open_unix.go b/internal/tailer/logstream/filestream_open_unix.go
new file mode 100644
index 000000000..bc1466bf5
--- /dev/null
+++ b/internal/tailer/logstream/filestream_open_unix.go
@@ -0,0 +1,14 @@
+// Copyright 2026 The mtail Authors. All Rights Reserved.
+// This file is available under the Apache license.
+
+//go:build !windows
+
+package logstream
+
+import (
+ "os"
+)
+
+func openFile(pathname string) (*os.File, error) {
+ return os.OpenFile(pathname, os.O_RDONLY, 0o600)
+}
diff --git a/internal/tailer/logstream/filestream_open_windows.go b/internal/tailer/logstream/filestream_open_windows.go
new file mode 100644
index 000000000..b409e2b31
--- /dev/null
+++ b/internal/tailer/logstream/filestream_open_windows.go
@@ -0,0 +1,31 @@
+// Copyright 2026 The mtail Authors. All Rights Reserved.
+// This file is available under the Apache license.
+
+//go:build windows
+
+package logstream
+
+import (
+ "os"
+ "syscall"
+)
+
+func openFile(pathname string) (*os.File, error) {
+ pathp, err := syscall.UTF16PtrFromString(pathname)
+ if err != nil {
+ return nil, &os.PathError{Op: "utf16", Path: pathname, Err: err}
+ }
+ handle, err := syscall.CreateFile(
+ pathp,
+ syscall.GENERIC_READ,
+ syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
+ nil,
+ syscall.OPEN_EXISTING,
+ syscall.FILE_ATTRIBUTE_NORMAL,
+ 0,
+ )
+ if err != nil {
+ return nil, &os.PathError{Op: "open", Path: pathname, Err: err}
+ }
+ return os.NewFile(uintptr(handle), pathname), nil
+}
diff --git a/internal/tailer/logstream/filestream_test.go b/internal/tailer/logstream/filestream_test.go
index 778a0f8dc..d1a432ef1 100644
--- a/internal/tailer/logstream/filestream_test.go
+++ b/internal/tailer/logstream/filestream_test.go
@@ -9,10 +9,10 @@ import (
"sync"
"testing"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
func TestFileStreamRead(t *testing.T) {
@@ -30,7 +30,7 @@ func TestFileStreamRead(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "yo"},
+ {Context: context.TODO(), Filename: name, Line: "yo", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -66,7 +66,7 @@ func TestFileStreamReadOneShot(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "yo"},
+ {Context: context.TODO(), Filename: name, Line: "yo", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -103,7 +103,7 @@ func TestFileStreamReadNonSingleByteEnd(t *testing.T) {
s += "δΈ"
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: s},
+ {Context: context.TODO(), Filename: name, Line: s, Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -151,7 +151,7 @@ func TestStreamDoesntBreakOnCorruptRune(t *testing.T) {
s += "a"
}
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: s[1:]},
+ {Context: context.TODO(), Filename: name, Line: s[1:], Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -188,9 +188,9 @@ func TestFileStreamTruncation(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "1"},
- {Context: context.TODO(), Filename: name, Line: "2"},
- {Context: context.TODO(), Filename: name, Line: "3"},
+ {Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)},
+ {Context: context.TODO(), Filename: name, Line: "2", Filenamehash: logline.GetHash(name)},
+ {Context: context.TODO(), Filename: name, Line: "3", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -231,7 +231,7 @@ func TestFileStreamPartialRead(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "yo"},
+ {Context: context.TODO(), Filename: name, Line: "yo", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -269,8 +269,8 @@ func TestFileStreamReadToEOFOnCancel(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "line 1"},
- {Context: context.TODO(), Filename: name, Line: "line 2"},
+ {Context: context.TODO(), Filename: name, Line: "line 1", Filenamehash: logline.GetHash(name)},
+ {Context: context.TODO(), Filename: name, Line: "line 2", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
diff --git a/internal/tailer/logstream/filestream_unix_test.go b/internal/tailer/logstream/filestream_unix_test.go
index 3971b6c50..038384843 100644
--- a/internal/tailer/logstream/filestream_unix_test.go
+++ b/internal/tailer/logstream/filestream_unix_test.go
@@ -11,18 +11,19 @@ import (
"path/filepath"
"sync"
"testing"
+ "time"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
-// TestFileStreamRotation is a unix-specific test because on Windows, files cannot be removed
-// or renamed while there is an open read handle on them. Instead, log rotation would
-// have to be implemented by copying and then truncating the original file. That test
-// case is already covered by TestFileStreamTruncation.
+// TestFileStreamRotation is a unix-specific test because rotation on Windows uses
+// FILE_SHARE_DELETE to allow rename while the file is open. The test currently
+// exercises the Unix path; Windows rotation via CopyFile+Delete is covered by
+// TestFileStreamTruncation.
func TestFileStreamRotation(t *testing.T) {
var wg sync.WaitGroup
@@ -40,8 +41,8 @@ func TestFileStreamRotation(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "1"},
- {Context: context.TODO(), Filename: name, Line: "2"},
+ {Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)},
+ {Context: context.TODO(), Filename: name, Line: "2", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -89,7 +90,7 @@ func TestFileStreamURL(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: name, Line: "yo"},
+ {Context: context.TODO(), Filename: name, Line: "yo", Filenamehash: logline.GetHash(name)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
@@ -108,6 +109,172 @@ func TestFileStreamURL(t *testing.T) {
}
}
+// manualWaker is a simple waker that lets the test directly signal wakeups
+// by closing and replacing the wake channel.
+type manualWaker struct {
+ wake chan struct{}
+}
+
+func (w *manualWaker) Wake() <-chan struct{} {
+ return w.wake
+}
+
+// wake signals the waker, closing the current channel and creating a new one.
+func (w *manualWaker) wakeAndReset() {
+ close(w.wake)
+ w.wake = make(chan struct{})
+}
+
+// TestFileStreamRotationPermissionDenied tests that when a rotation is detected
+// and the new file cannot be opened (permission denied), the filestream closes
+// its Lines channel so the tailer can clean up and retry later.
+func TestFileStreamRotationPermissionDenied(t *testing.T) {
+ testutil.SkipIfRoot(t)
+ var wg sync.WaitGroup
+
+ tmpDir := testutil.TestTempDir(t)
+
+ name := filepath.Join(tmpDir, "log")
+ f := testutil.TestOpenFile(t, name)
+ defer f.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ mw := &manualWaker{wake: make(chan struct{})}
+
+ fs, err := logstream.New(ctx, &wg, mw, name, logstream.OneShotDisabled)
+ testutil.FatalIfErr(t, err)
+
+ expectedLines := []*logline.LogLine{
+ {Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)},
+ }
+ checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expectedLines, fs.Lines())
+
+ mw.wakeAndReset() // sync to EOF
+
+ testutil.WriteString(t, f, "1\n")
+ mw.wakeAndReset()
+
+ // Rotate: rename old file, create new file with no read permissions.
+ testutil.FatalIfErr(t, os.Rename(name, name+".1"))
+ f2, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0)
+ testutil.FatalIfErr(t, err)
+ f2.Close()
+
+ // Wake the stream to detect rotation. The goroutine will see a new
+ // inode, try to open the new file, fail with permission denied, and
+ // (with our fix) close fs.lines.
+ mw.wakeAndReset()
+
+ // Wait for the Lines channel to close, indicating the goroutine exited.
+ ok, err := testutil.DoOrTimeout(func() (bool, error) {
+ select {
+ case _, stillOpen := <-fs.Lines():
+ return !stillOpen, nil
+ default:
+ return false, nil
+ }
+ }, time.Second, 10*time.Millisecond)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !ok {
+ t.Error("Lines channel not closed after rotation + permission denied")
+ }
+
+ // Wait for the goroutine to fully shut down.
+ wg.Wait()
+
+ // Fix permissions on the new file.
+ testutil.FatalIfErr(t, os.Chmod(name, 0o666))
+
+ // Now create a new stream; this should succeed.
+ fs2, err := logstream.New(ctx, &wg, mw, name, logstream.OneShotDisabled)
+ testutil.FatalIfErr(t, err)
+
+ expectedLines2 := []*logline.LogLine{
+ {Context: context.TODO(), Filename: name, Line: "2", Filenamehash: logline.GetHash(name)},
+ }
+ checkLineDiff2 := testutil.ExpectLinesReceivedNoDiff(t, expectedLines2, fs2.Lines())
+
+ f3, err := os.OpenFile(name, os.O_RDWR|os.O_APPEND, 0o666)
+ testutil.FatalIfErr(t, err)
+ defer f3.Close()
+
+ mw.wakeAndReset() // sync to EOF
+
+ testutil.WriteString(t, f3, "2\n")
+ mw.wakeAndReset()
+
+ cancel()
+ wg.Wait()
+
+ checkLineDiff()
+ checkLineDiff2()
+}
+
+// TestFileStreamStatErrorNotExist tests that when a file being tailed is
+// deleted, the filestream's stat call returns a NotExist error and the
+// stream properly closes its Lines channel, letting the tailer clean up
+// and retry later. This exercises the same stat-error path that handles
+// ESTALE in production (both trigger stream shutdown).
+func TestFileStreamStatErrorNotExist(t *testing.T) {
+ var wg sync.WaitGroup
+
+ tmpDir := testutil.TestTempDir(t)
+
+ name := filepath.Join(tmpDir, "log")
+ f := testutil.TestOpenFile(t, name)
+ defer f.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ mw := &manualWaker{wake: make(chan struct{})}
+
+ fs, err := logstream.New(ctx, &wg, mw, name, logstream.OneShotDisabled)
+ testutil.FatalIfErr(t, err)
+
+ expected := []*logline.LogLine{
+ {Context: context.TODO(), Filename: name, Line: "1", Filenamehash: logline.GetHash(name)},
+ }
+ checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, fs.Lines())
+
+ mw.wakeAndReset() // sync to EOF
+
+ testutil.WriteString(t, f, "1\n")
+ mw.wakeAndReset()
+
+ // Delete the file. The stream will stat the path at the next EOF,
+ // get a NotExist error, and close its Lines channel.
+ testutil.FatalIfErr(t, os.Remove(name))
+ mw.wakeAndReset()
+
+ // Wait for the Lines channel to close.
+ ok, err := testutil.DoOrTimeout(func() (bool, error) {
+ select {
+ case _, stillOpen := <-fs.Lines():
+ return !stillOpen, nil
+ default:
+ return false, nil
+ }
+ }, time.Second, 10*time.Millisecond)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !ok {
+ t.Error("Lines channel not closed after file deletion")
+ }
+ wg.Wait()
+
+ checkLineDiff()
+
+ if v := <-fs.Lines(); v != nil {
+ t.Errorf("expecting filestream to be complete because file deleted")
+ }
+}
+
// TestFileStreamOpenFailure is a unix-specific test because on Windows, it is not possible to create a file
// that you yourself cannot read (minimum permissions are 0222).
func TestFileStreamOpenFailure(t *testing.T) {
diff --git a/internal/tailer/logstream/logstream.go b/internal/tailer/logstream/logstream.go
index 7dbd5314a..b53ef11da 100644
--- a/internal/tailer/logstream/logstream.go
+++ b/internal/tailer/logstream/logstream.go
@@ -18,8 +18,8 @@ import (
"sync"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/waker"
)
var (
@@ -85,6 +85,9 @@ func New(ctx context.Context, wg *sync.WaitGroup, waker waker.Waker, pathname st
return newDgramStream(ctx, wg, waker, u.Scheme, u.Host, oneShot)
case "", "file":
path = u.Path
+ if u.RawFragment != "" {
+ path += "#" + u.RawFragment
+ }
}
if IsStdinPattern(path) {
fi, err := os.Stdin.Stat()
diff --git a/internal/tailer/logstream/logstream_test.go b/internal/tailer/logstream/logstream_test.go
index 3fceebe59..500cff23c 100644
--- a/internal/tailer/logstream/logstream_test.go
+++ b/internal/tailer/logstream/logstream_test.go
@@ -2,10 +2,12 @@ package logstream_test
import (
"context"
+ "os"
"sync"
"testing"
- "github.com/google/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/waker"
)
func TestNewErrors(t *testing.T) {
@@ -20,3 +22,23 @@ func TestNewErrors(t *testing.T) {
t.Error("New(ctg, wg, ..., path) expecting error, received nil")
}
}
+
+func TestPathNameWithHash(t *testing.T) {
+ ctx := context.Background()
+ var wg sync.WaitGroup
+ file, err := os.CreateTemp("", "4c9_1#1_2.3.4.a.b114514#1bcd.log")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(file.Name())
+ defer file.Close()
+ wk := waker.NewTestAlways()
+ _, err = logstream.New(ctx, &wg, wk, file.Name(), logstream.OneShotDisabled)
+ if err != nil {
+ t.Errorf("New(ctx, nil) expecting nil, received error: %v", err)
+ }
+ _, err = logstream.New(ctx, &wg, wk, "file://"+file.Name(), logstream.OneShotDisabled)
+ if err != nil {
+ t.Errorf("New(ctx, nil) expecting nil, received error: %v", err)
+ }
+}
diff --git a/internal/tailer/logstream/logstream_unix_test.go b/internal/tailer/logstream/logstream_unix_test.go
index 03a2091f9..ae24c5a74 100644
--- a/internal/tailer/logstream/logstream_unix_test.go
+++ b/internal/tailer/logstream/logstream_unix_test.go
@@ -9,8 +9,8 @@ import (
"sync"
"testing"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/testutil"
"golang.org/x/sys/unix"
)
diff --git a/internal/tailer/logstream/reader.go b/internal/tailer/logstream/reader.go
index 167c9c414..b6e63f67d 100644
--- a/internal/tailer/logstream/reader.go
+++ b/internal/tailer/logstream/reader.go
@@ -10,7 +10,7 @@ import (
"io"
"time"
- "github.com/google/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/logline"
)
// logLines counts the number of lines read per log file.
@@ -18,11 +18,12 @@ var logLines = expvar.NewMap("log_lines_total")
// LineReader reads lines from input and sends lines through the channel
type LineReader struct {
- sourcename string // name of owner, for sending loglines
- lines chan<- *logline.LogLine // not owned
- f io.Reader // not owned
- cancel context.CancelFunc
- staleTimer *time.Timer // call CancelFunc if no read in 24h
+ sourcename string // name of owner, for sending loglines
+ sourcenamehash uint32 // a hash of the sourcename for efficient lookup
+ lines chan<- *logline.LogLine // not owned
+ f io.Reader // not owned
+ cancel context.CancelFunc
+ staleTimer *time.Timer // call CancelFunc if no read in 24h
size int
buf []byte
@@ -32,12 +33,13 @@ type LineReader struct {
// NewLineReader creates a new LineReader
func NewLineReader(sourcename string, lines chan<- *logline.LogLine, f io.Reader, size int, cancel context.CancelFunc) *LineReader {
return &LineReader{
- sourcename: sourcename,
- lines: lines,
- f: f,
- cancel: cancel,
- size: size,
- buf: make([]byte, 0, size),
+ sourcename: sourcename,
+ sourcenamehash: logline.GetHash(sourcename),
+ lines: lines,
+ f: f,
+ cancel: cancel,
+ size: size,
+ buf: make([]byte, 0, size),
}
}
@@ -89,7 +91,7 @@ func (lr *LineReader) send(ctx context.Context) bool {
line := string(lr.buf[lr.off:end])
logLines.Add(lr.sourcename, 1)
- lr.lines <- logline.New(ctx, lr.sourcename, line)
+ lr.lines <- logline.New(ctx, lr.sourcename, lr.sourcenamehash, line)
lr.off = end + skip // move past delim
return true
}
@@ -102,5 +104,5 @@ func (lr *LineReader) Finish(ctx context.Context) {
return
}
logLines.Add(lr.sourcename, 1)
- lr.lines <- logline.New(ctx, lr.sourcename, line)
+ lr.lines <- logline.New(ctx, lr.sourcename, lr.sourcenamehash, line)
}
diff --git a/internal/tailer/logstream/reader_test.go b/internal/tailer/logstream/reader_test.go
index 33e897e15..80ac2f053 100644
--- a/internal/tailer/logstream/reader_test.go
+++ b/internal/tailer/logstream/reader_test.go
@@ -13,8 +13,8 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestReadAndSend(t *testing.T) {
diff --git a/internal/tailer/logstream/socketstream.go b/internal/tailer/logstream/socketstream.go
index 1e96d3397..eb52e4153 100644
--- a/internal/tailer/logstream/socketstream.go
+++ b/internal/tailer/logstream/socketstream.go
@@ -10,8 +10,8 @@ import (
"sync"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/waker"
)
type socketStream struct {
diff --git a/internal/tailer/logstream/socketstream_unix_test.go b/internal/tailer/logstream/socketstream_unix_test.go
index 0ffad74df..90688d90f 100644
--- a/internal/tailer/logstream/socketstream_unix_test.go
+++ b/internal/tailer/logstream/socketstream_unix_test.go
@@ -14,10 +14,10 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
func TestSocketStreamReadCompletedBecauseSocketClosed(t *testing.T) {
@@ -32,7 +32,7 @@ func TestSocketStreamReadCompletedBecauseSocketClosed(t *testing.T) {
tmpDir := testutil.TestTempDir(t)
addr = filepath.Join(tmpDir, "sock")
case "tcp":
- addr = fmt.Sprintf("[::]:%d", testutil.FreePort(t))
+ addr = fmt.Sprintf("127.0.0.1:%d", testutil.FreePort(t))
default:
t.Fatalf("bad scheme %s", scheme)
}
@@ -47,7 +47,7 @@ func TestSocketStreamReadCompletedBecauseSocketClosed(t *testing.T) {
testutil.FatalIfErr(t, err)
expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: sockName, Line: "1"},
+ {Context: context.TODO(), Filename: sockName, Line: "1", Filenamehash: logline.GetHash(sockName)},
}
checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ss.Lines())
@@ -83,7 +83,7 @@ func TestSocketStreamReadCompletedBecauseCancel(t *testing.T) {
tmpDir := testutil.TestTempDir(t)
addr = filepath.Join(tmpDir, "sock")
case "tcp":
- addr = fmt.Sprintf("[::]:%d", testutil.FreePort(t))
+ addr = fmt.Sprintf("127.0.0.1:%d", testutil.FreePort(t))
default:
t.Fatalf("bad scheme %s", scheme)
}
@@ -95,25 +95,22 @@ func TestSocketStreamReadCompletedBecauseCancel(t *testing.T) {
ss, err := logstream.New(ctx, &wg, waker, sockName, logstream.OneShotDisabled)
testutil.FatalIfErr(t, err)
- expected := []*logline.LogLine{
- {Context: context.TODO(), Filename: sockName, Line: "1"},
- }
- checkLineDiff := testutil.ExpectLinesReceivedNoDiff(t, expected, ss.Lines())
-
s, err := net.Dial(scheme, addr)
testutil.FatalIfErr(t, err)
_, err = s.Write([]byte("1\n"))
testutil.FatalIfErr(t, err)
- // Yield to give the stream a chance to read.
- time.Sleep(10 * time.Millisecond)
+ // Read from Lines to synchronise with the stream goroutine: this
+ // blocks until the stream has consumed the data, proving it read
+ // "1\n" from the socket before we cancel.
+ expected := &logline.LogLine{Context: context.TODO(), Filename: sockName, Line: "1", Filenamehash: logline.GetHash(sockName)}
+ received := <-ss.Lines()
+ testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
- cancel() // This cancellation should cause the stream to shut down immediately.
+ cancel() // This cancellation should cause the stream to shut down.
wg.Wait()
- checkLineDiff()
-
if v := <-ss.Lines(); v != nil {
t.Errorf("expecting socketstream to be complete because cancel")
}
diff --git a/internal/tailer/tail.go b/internal/tailer/tail.go
index cba63ffa9..76f1302b4 100644
--- a/internal/tailer/tail.go
+++ b/internal/tailer/tail.go
@@ -17,9 +17,9 @@ import (
"sync"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/tailer/logstream"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/tailer/logstream"
+ "github.com/jaqx0r/mtail/internal/waker"
)
// logCount records the number of logs that are being tailed.
diff --git a/internal/tailer/tail_test.go b/internal/tailer/tail_test.go
index c019d52f2..ff7efc599 100644
--- a/internal/tailer/tail_test.go
+++ b/internal/tailer/tail_test.go
@@ -11,9 +11,9 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/testutil"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/waker"
)
type testTail struct {
@@ -99,10 +99,10 @@ func TestHandleLogUpdate(t *testing.T) {
received := testutil.LinesReceived(ta.lines)
expected := []*logline.LogLine{
- {Context: context.Background(), Filename: logfile, Line: "a"},
- {Context: context.Background(), Filename: logfile, Line: "b"},
- {Context: context.Background(), Filename: logfile, Line: "c"},
- {Context: context.Background(), Filename: logfile, Line: "d"},
+ {Context: context.Background(), Filename: logfile, Line: "a", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "b", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "c", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "d", Filenamehash: logline.GetHash(logfile)},
}
testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
}
@@ -140,11 +140,11 @@ func TestHandleLogTruncate(t *testing.T) {
received := testutil.LinesReceived(ta.lines)
expected := []*logline.LogLine{
- {Context: context.Background(), Filename: logfile, Line: "a"},
- {Context: context.Background(), Filename: logfile, Line: "b"},
- {Context: context.Background(), Filename: logfile, Line: "c"},
- {Context: context.Background(), Filename: logfile, Line: "d"},
- {Context: context.Background(), Filename: logfile, Line: "e"},
+ {Context: context.Background(), Filename: logfile, Line: "a", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "b", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "c", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "d", Filenamehash: logline.GetHash(logfile)},
+ {Context: context.Background(), Filename: logfile, Line: "e", Filenamehash: logline.GetHash(logfile)},
}
testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
}
@@ -172,7 +172,7 @@ func TestHandleLogUpdatePartialLine(t *testing.T) {
received := testutil.LinesReceived(ta.lines)
expected := []*logline.LogLine{
- {Context: context.Background(), Filename: logfile, Line: "ab"},
+ {Context: context.Background(), Filename: logfile, Line: "ab", Filenamehash: logline.GetHash(logfile)},
}
testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
}
diff --git a/internal/tailer/tail_unix_test.go b/internal/tailer/tail_unix_test.go
index 384806540..5bb2c1c1e 100644
--- a/internal/tailer/tail_unix_test.go
+++ b/internal/tailer/tail_unix_test.go
@@ -12,8 +12,8 @@ import (
"testing"
"github.com/golang/glog"
- "github.com/google/mtail/internal/logline"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/testutil"
"golang.org/x/sys/unix"
)
@@ -69,7 +69,7 @@ func TestTailerOpenRetries(t *testing.T) {
received := testutil.LinesReceived(ta.lines)
expected := []*logline.LogLine{
- {Context: context.Background(), Filename: logfile, Line: ""},
+ {Context: context.Background(), Filename: logfile, Line: "", Filenamehash: logline.GetHash(logfile)},
}
testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
}
@@ -92,7 +92,7 @@ func TestAddStdin(t *testing.T) {
received := testutil.LinesReceived(ta.lines)
expected := []*logline.LogLine{
- {Context: context.Background(), Filename: "-", Line: "content"},
+ {Context: context.Background(), Filename: "-", Line: "content", Filenamehash: logline.GetHash("-")},
}
testutil.ExpectNoDiff(t, expected, received, testutil.IgnoreFields(logline.LogLine{}, "Context"))
}
diff --git a/internal/tailer/tail_windows_test.go b/internal/tailer/tail_windows_test.go
index 7a2cef44f..29748e5ac 100644
--- a/internal/tailer/tail_windows_test.go
+++ b/internal/tailer/tail_windows_test.go
@@ -8,7 +8,7 @@ package tailer
import (
"testing"
- "github.com/google/mtail/internal/testutil"
+ "github.com/jaqx0r/mtail/internal/testutil"
)
func TestWindowsPath(t *testing.T) {
diff --git a/internal/testutil/BUILD.bazel b/internal/testutil/BUILD.bazel
new file mode 100644
index 000000000..5da62a3dd
--- /dev/null
+++ b/internal/testutil/BUILD.bazel
@@ -0,0 +1,36 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "testutil",
+ srcs = [
+ "diff.go",
+ "err.go",
+ "expvar.go",
+ "file.go",
+ "flag.go",
+ "fs.go",
+ "lines.go",
+ "norace.go",
+ "port.go",
+ "race.go",
+ "root.go",
+ "short.go",
+ "stdin.go",
+ "timeout.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/testutil",
+ visibility = ["//:__subpackages__"],
+ deps = [
+ "//internal/logline",
+ "@com_github_golang_glog//:glog",
+ "@com_github_google_go_cmp//cmp",
+ "@com_github_google_go_cmp//cmp/cmpopts",
+ ],
+)
+
+go_test(
+ name = "testutil_test",
+ size = "small",
+ srcs = ["timeout_test.go"],
+ embed = [":testutil"],
+)
diff --git a/internal/testutil/fs.go b/internal/testutil/fs.go
index 0d634881b..524f7ab3f 100644
--- a/internal/testutil/fs.go
+++ b/internal/testutil/fs.go
@@ -10,8 +10,14 @@ import (
)
// TestTempDir creates a temporary directory for use during tests, returning the pathname.
+//
+// We don't use tb.TempDir() beacuse generates temp directories based on the
+// test name, which is often longer than 108 characters, which then breaks the
+// unix socket tests because elsewhere in Go only 108 character socket
+// pathnames are supported!. https://github.com/golang/go/issues/6895
func TestTempDir(tb testing.TB) string {
tb.Helper()
+ //nolint:usetesting
name, err := os.MkdirTemp("", "mtail-test")
if err != nil {
tb.Fatal(err)
diff --git a/internal/testutil/lines.go b/internal/testutil/lines.go
index 7292e05b5..99ad85468 100644
--- a/internal/testutil/lines.go
+++ b/internal/testutil/lines.go
@@ -7,7 +7,7 @@ import (
"sync"
"testing"
- "github.com/google/mtail/internal/logline"
+ "github.com/jaqx0r/mtail/internal/logline"
)
func LinesReceived(lines <-chan *logline.LogLine) (r []*logline.LogLine) {
diff --git a/internal/testutil/port.go b/internal/testutil/port.go
index 9d928b78c..7bb009562 100644
--- a/internal/testutil/port.go
+++ b/internal/testutil/port.go
@@ -9,13 +9,22 @@ import (
func FreePort(tb testing.TB) int {
tb.Helper()
+ // Try IPv6 first, fall back to IPv4 on environments without IPv6 (e.g. BuildBuddy RBE).
addr, err := net.ResolveTCPAddr("tcp", "[::]:0")
if err != nil {
tb.Fatal(err)
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
- tb.Fatal(err)
+ // Fall back to IPv4.
+ addr4, err4 := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
+ if err4 != nil {
+ tb.Fatal(err4)
+ }
+ l, err = net.ListenTCP("tcp", addr4)
+ if err != nil {
+ tb.Fatal(err)
+ }
}
defer l.Close()
return l.Addr().(*net.TCPAddr).Port
diff --git a/internal/waker/BUILD.bazel b/internal/waker/BUILD.bazel
new file mode 100644
index 000000000..f2773b2d0
--- /dev/null
+++ b/internal/waker/BUILD.bazel
@@ -0,0 +1,23 @@
+load("@rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "waker",
+ srcs = [
+ "testwaker.go",
+ "timedwaker.go",
+ "waker.go",
+ ],
+ importpath = "github.com/jaqx0r/mtail/internal/waker",
+ visibility = ["//:__subpackages__"],
+ deps = ["@com_github_golang_glog//:glog"],
+)
+
+go_test(
+ name = "waker_test",
+ size = "small",
+ srcs = [
+ "testwaker_test.go",
+ "timedwaker_test.go",
+ ],
+ deps = [":waker"],
+)
diff --git a/internal/waker/testwaker_test.go b/internal/waker/testwaker_test.go
index 2eaf6b153..99130c2d6 100644
--- a/internal/waker/testwaker_test.go
+++ b/internal/waker/testwaker_test.go
@@ -8,7 +8,7 @@ import (
"sync"
"testing"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/waker"
)
func TestTestWakerWakes(t *testing.T) {
diff --git a/internal/waker/timedwaker_test.go b/internal/waker/timedwaker_test.go
index f9cc1febc..a93e745bf 100644
--- a/internal/waker/timedwaker_test.go
+++ b/internal/waker/timedwaker_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"time"
- "github.com/google/mtail/internal/waker"
+ "github.com/jaqx0r/mtail/internal/waker"
)
func TestTimedWakerWakes(t *testing.T) {
diff --git a/mtail.service b/mtail.service
index 0d0986072..e73359734 100644
--- a/mtail.service
+++ b/mtail.service
@@ -1,6 +1,6 @@
[Unit]
-Description=mtail - extracts metrics from logs
-Documentation=https://github.com/google/mtail/tree/main/docs
+Description=mtail - extract internal monitoring data from application logs for collection in a timeseries database
+Documentation=https://jaqx0r.github.io/
Requires=local-fs.target network.target
Before=nss-user-lookup.target
After=local-fs.target network.target
@@ -19,7 +19,6 @@ AmbientCapabilities=
CapabilityBoundingSet=
KeyringMode=private
LockPersonality=yes
-LockPersonality=yes
MemoryDenyWriteExecute=yes
MountFlags=private
NoNewPrivileges=yes
@@ -40,7 +39,7 @@ RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
-SystemCallFilter=@basic-io @file-system @io-event @ipc @network-io @signal clone kill madvise setrlimit tgkill uname
+SystemCallFilter=@default
[Install]
WantedBy=multi-user.target
diff --git a/release/BUILD.bazel b/release/BUILD.bazel
new file mode 100644
index 000000000..89759d24f
--- /dev/null
+++ b/release/BUILD.bazel
@@ -0,0 +1,117 @@
+load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template")
+load("@rules_go//go:def.bzl", "go_cross_binary")
+load("@rules_img//img:image.bzl", "image_index", "image_manifest")
+load("@rules_img//img:layer.bzl", "image_layer")
+load("@rules_img//img:load.bzl", "image_load")
+load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
+
+# Build an mtail binary for supported platforms.
+PLATFORMS = [
+ "linux_386",
+ "linux_amd64",
+ "linux_arm64",
+ "windows_386",
+ "windows_amd64",
+ "windows_arm64",
+ "darwin_amd64",
+ "darwin_arm64",
+]
+
+[
+ go_cross_binary(
+ name = "mtail_" + platform,
+ platform = "@rules_go//go/toolchain:" + platform,
+ target = "//cmd/mtail",
+ )
+ for platform in PLATFORMS
+]
+
+filegroup(
+ name = "cross_build",
+ srcs = [":mtail_" + platform for platform in PLATFORMS],
+)
+
+[
+ pkg_tar(
+ name = "tarball_" + platform,
+ srcs = [
+ ":mtail_" + platform,
+ "//:docs",
+ ],
+ out = "mtail_" + platform + ".tar.gz",
+ extension = "tar.gz",
+ stamp = -1,
+ )
+ for platform in PLATFORMS
+]
+
+image_layer(
+ name = "mtail_layer",
+ srcs = {
+ "/mtail": "//cmd/mtail",
+ },
+)
+
+_TIMESTAMP_STRING = "2006-01-02T15:04:05Z"
+
+expand_template(
+ name = "timestamp",
+ out = "timestamp.txt",
+ stamp_substitutions = {
+ _TIMESTAMP_STRING: "{{BUILD_TIMESTAMP_ISO8601}}",
+ },
+ template = [_TIMESTAMP_STRING],
+)
+
+image_manifest(
+ name = "manifest",
+ base = "@distroless_base",
+ config_fragment = "config.json",
+ created = ":timestamp",
+ entrypoint = ["/mtail"],
+ labels = {
+ "org.opencontainers.image.ref.name": "jaqx0r/mtail",
+ "org.opencontainers.image.title": "mtail",
+ "org.opencontainers.image.description": "extract internal monitoring data from application logs for collection in a timeseries database",
+ "org.opencontainers.image.authors": "Jamie Wilkinson (@jaqx0r)",
+ "org.opencontainers.image.licenses": "Apache-2.0",
+ "org.opencontainers.image.version": "{{if .STABLE_GIT_SEMVER}}{{.STABLE_GIT_SEMVER}}{{else}}0.0.0{{end}}",
+ "org.opencontainers.image.revision": "{{if .STABLE_GIT_REVISION}}{{.STABLE_GIT_REVISION}}{{else}}unknown{{end}}",
+ "org.opencontainers.image.source": "https://github.com/jaqx0r/mtail/",
+ "org.opencontainers.image.documentation": "https://jaqx0r.github.io/mtail/",
+ "org.opencontainers.image.created": "{{.BUILD_TIMESTAMP}}",
+ "org.opencontainers.image.url": "https://github.com/jaqx0r/mtail",
+ },
+ layers = [":mtail_layer"],
+)
+
+image_index(
+ name = "image",
+ manifests = [":manifest"],
+ platforms = [
+ ":linux_amd64",
+ ":linux_arm64v8",
+ ],
+)
+
+platform(
+ name = "linux_amd64",
+ constraint_values = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ ],
+)
+
+platform(
+ name = "linux_arm64v8",
+ constraint_values = [
+ "@platforms//os:linux",
+ "@platforms//cpu:aarch64",
+ ],
+)
+
+image_load(
+ name = "load_image",
+ image = ":image",
+ tag_list = ["mtail:latest"],
+)
diff --git a/release/config.json b/release/config.json
new file mode 100644
index 000000000..0cb40c158
--- /dev/null
+++ b/release/config.json
@@ -0,0 +1,7 @@
+{
+ "config": {
+ "ExposedPorts": {
+ "3903/tcp": {}
+ }
+ }
+}
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 000000000..bf8d2aba6
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": [
+ "config:recommended",
+ ":automergeAll",
+ ":automergePr"
+ ],
+ "postUpdateOptions": ["gomodTidy"]
+}
diff --git a/subject_summarizer.mtail b/subject_summarizer.mtail
index 5e8a533b0..a56283a05 100644
--- a/subject_summarizer.mtail
+++ b/subject_summarizer.mtail
@@ -7,6 +7,6 @@ counter subject_lines_seen by subject
const SUBJECT_LINE /^Subject: (.*)$/
-// + SUBJECT_LINE {
+SUBJECT_LINE {
subject_lines_seen[$1] ++
}