Repository: aternosorg/mclogs Branch: main Commit: 5269341d2bad Files: 98 Total size: 217.8 KB Directory structure: gitextract_kqffgv0b/ ├── .dockerignore ├── .github/ │ └── workflows/ │ └── publish.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── build.php ├── composer.json ├── dev/ │ ├── compose.yaml │ └── dev.ini ├── docker/ │ ├── Caddyfile │ ├── compose.production.yaml │ └── mclogs.ini ├── example.config.json ├── src/ │ ├── Api/ │ │ ├── Action/ │ │ │ ├── AnalyseLogAction.php │ │ │ ├── ApiAction.php │ │ │ ├── BulkDeleteLogsAction.php │ │ │ ├── CreateLogAction.php │ │ │ ├── DeleteLogAction.php │ │ │ ├── EmptyAction.php │ │ │ ├── EndpointNotFoundAction.php │ │ │ ├── GetFiltersAction.php │ │ │ ├── GetLimitsAction.php │ │ │ ├── LogInfoAction.php │ │ │ ├── LogInsightsAction.php │ │ │ ├── RateLimitErrorAction.php │ │ │ └── RawLogAction.php │ │ ├── ApiRouter.php │ │ ├── ContentParser.php │ │ ├── LogContentParser.php │ │ └── Response/ │ │ ├── ApiError.php │ │ ├── ApiResponse.php │ │ ├── CodexLogResponse.php │ │ ├── FiltersResponse.php │ │ ├── LimitsResponse.php │ │ ├── LogResponse.php │ │ ├── MultiResponse.php │ │ └── RawLogResponse.php │ ├── Cache/ │ │ └── CacheEntry.php │ ├── Config/ │ │ ├── Config.php │ │ └── ConfigKey.php │ ├── Data/ │ │ ├── Deobfuscator.php │ │ ├── MetadataEntry.php │ │ └── Token.php │ ├── Detective.php │ ├── Filter/ │ │ ├── AccessTokenFilter.php │ │ ├── Filter.php │ │ ├── FilterType.php │ │ ├── IPv4Filter.php │ │ ├── IPv6Filter.php │ │ ├── LimitBytesFilter.php │ │ ├── LimitLinesFilter.php │ │ ├── Pattern/ │ │ │ ├── Modifier.php │ │ │ ├── Pattern.php │ │ │ └── PatternWithReplacement.php │ │ ├── RegexFilter.php │ │ ├── TrimFilter.php │ │ └── UsernameFilter.php │ ├── Frontend/ │ │ ├── Action/ │ │ │ ├── ApiDocsAction.php │ │ │ ├── CreateLogAction.php │ │ │ ├── DeleteLogAction.php │ │ │ ├── FaviconAction.php │ │ │ ├── NotFoundAction.php │ │ │ ├── StartAction.php │ │ │ └── ViewLogAction.php │ │ ├── Assets/ │ │ │ ├── Asset.php │ │ │ ├── AssetLoader.php │ │ │ └── AssetType.php │ │ ├── Cookie/ │ │ │ ├── Cookie.php │ │ │ ├── SettingsCookie.php │ │ │ └── TokenCookie.php │ │ ├── FrontendRouter.php │ │ └── Settings/ │ │ ├── Setting.php │ │ └── Settings.php │ ├── Id.php │ ├── Log.php │ ├── Printer/ │ │ ├── FormatModification.php │ │ └── Printer.php │ ├── Router/ │ │ ├── Action.php │ │ ├── Method.php │ │ ├── Route.php │ │ └── Router.php │ ├── Storage/ │ │ └── MongoDBClient.php │ └── Util/ │ ├── Singleton.php │ ├── TimeInterval.php │ └── URL.php ├── web/ │ ├── frontend/ │ │ ├── 404.php │ │ ├── api-docs.php │ │ ├── log.php │ │ ├── parts/ │ │ │ ├── favicon.php │ │ │ ├── footer.php │ │ │ ├── head.php │ │ │ └── header.php │ │ └── start.php │ └── public/ │ ├── css/ │ │ └── mclogs.css │ └── js/ │ ├── log.js │ └── start.js └── worker.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ vendor/ .git/ .github/ Dockerfile ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish Docker Image on: push: branches: - 'main' tags: - 'v*' env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: build-and-push: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Log in to the Container registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | # Branch Name (e.g. 'two', 'main') type=ref,event=branch # Full Version (e.g. '1.2.3') type=semver,pattern={{version}} # Major Version (e.g. '1') type=semver,pattern={{major}} # Major.Minor (e.g. '1.2') type=semver,pattern={{major}}.{{minor}} # Latest (Only on release tags) type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 cache-from: | type=gha type=gha,scope=refs/heads/main cache-to: type=gha,mode=max ================================================ FILE: .gitignore ================================================ *.log *.cache .idea /vendor/ config.json ================================================ FILE: Dockerfile ================================================ FROM dunglas/frankenphp:1-php8.5 # System Setup RUN install-php-extensions mongodb zip ARG USER=mclogs RUN useradd ${USER} && \ setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp COPY --from=composer/composer:2-bin /composer /usr/bin/composer WORKDIR /app # Dependencies (Cached) COPY composer.json composer.lock ./ RUN --mount=type=cache,target=/tmp/cache/composer \ COMPOSER_CACHE_DIR=/tmp/cache/composer \ composer install --no-dev --no-interaction --no-scripts --no-autoloader --prefer-dist --ignore-platform-req=ext-frankenphp # Application Setup COPY docker/Caddyfile /etc/frankenphp/Caddyfile COPY docker/mclogs.ini /usr/local/etc/php/conf.d/mclogs.ini COPY . . RUN composer dump-autoload --optimize --no-dev --classmap-authoritative RUN php build.php # Permissions & Runtime RUN chown -R ${USER}:${USER} /config/caddy /data/caddy /app USER ${USER} EXPOSE 80 EXPOSE 443 EXPOSE 443/udp VOLUME ["/data"] ================================================ FILE: LICENSE ================================================ Copyright (c) 2018-2024 Aternos GmbH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================
Paste, share & analyse your logs
Built for Minecraft & Hytale
Integrate = htmlspecialchars($config->getName()); ?> directly into your server panel, your hosting software or anything else. This platform was built for high performance automation and can easily be integrated into any existing software via our HTTP API.
| Field | Required | Type | Description |
|---|---|---|---|
| content | string | The raw log file content as string. Limited to = number_format($config->get(ConfigKey::STORAGE_LIMIT_BYTES) / 1024 / 1024, 2); ?> MiB and = number_format($config->get(ConfigKey::STORAGE_LIMIT_LINES)); ?> lines. Will be truncated if possible and necessary, but truncating on the client side is recommended. | |
| source | string | The name of the source, e.g. a domain or software name. | |
| metadata | array | An array of metadata entries. |
{
"content": "[log file content...]",
"source": "example.org"
}
You can send metadata alongside the log content to be displayed on the log page and/or be read by other applications through this API. This is entirely optional, but can help to provide additional context, e.g. internal server IDs, software versions etc.
A metadata entry is an object with the following fields:
| Field | Required | Type | Description |
|---|---|---|---|
| key | string | The metadata key. Can be used to identify the entry in your code later. | |
| value | string|int|float|bool|null | The metadata value. | |
| label | string | The display label. If not provided, the key will be used as label. | |
| visible | bool | Whether this metadata should be visible on the log page or is only available through the API. Default is true. |
{
"content": "[log file content...]",
"source": "example.org",
"metadata": [
{
"key": "server_id",
"value": 12345,
"visible": false
},
{
"key": "software_version",
"value": "1.2.3",
"label": "Software Version",
"visible": true
}
]
}
{
"success":true,
"id":"WnMMikq",
"source":null,
"created":1769597979,
"expires":1777373979,
"size":157369,
"lines":1201,
"errors":8,
"url": "= htmlspecialchars(URL::getBase()->withPath("/WnMMikq")->toString()); ?>",
"raw": "= htmlspecialchars(URL::getApi()->withPath("/1/raw/WnMMikq")->toString()); ?>",
"token":"78351fafe495398163fff847f9a26dda440435dcf7b5f92e8e36308f3683d771",
"metadata": [
{
"key": "server_id",
"value": 12345,
"visible": false
},
{
"key": "software_version",
"value": "1.2.3",
"label": "Software Version",
"visible": true
}
]
}
{
"success": false,
"error": "Required field 'content' not found."
}
This endpoint only returns the log info and metadata by default (same response as creating a log), you can also get the content in the same request by enabling it in different formats using GET parameters. You can combine multiple parameters to get multiple content formats in one request, but keep in mind that this will increase the response size.
| GET Parameter | Response field | Description |
|---|---|---|
| raw | content.raw | Includes the raw log content as string in the response. |
| parsed | content.parsed | Includes the parsed log content as array/objects in the response. |
| insights | content.insights | Includes the automatically detected insights in the response. |
{
"success":true,
"id":"WnMMikq",
"source":null,
"created":1769597979,
"expires":1777373979,
"size":157369,
"lines":1201,
"errors":8,
"url": "= htmlspecialchars(URL::getBase()->withPath("/WnMMikq")->toString()); ?>",
"raw": "= htmlspecialchars(URL::getApi()->withPath("/1/raw/WnMMikq")->toString()); ?>",
"metadata": [
{
"key": "server_id",
"value": 12345,
"visible": false
},
{
"key": "software_version",
"value": "1.2.3",
"label": "Software Version",
"visible": true
}
],
"content": {
"raw": "[log file content...]",
"parsed": [ /* parsed log entries */ ],
"insights": { "problems": [ /* detected problems */ ], "information": [ /* detected information */ ] }
}
}
{
"success": false,
"error": "Log not found."
}
| Header | Example | Description |
|---|---|---|
| Authorization | Authorization: Bearer 78351fafe495398163f... | The type (always "Bearer") and the log token received when creating the log. |
{
"success": true
}
{
"success": false,
"error": "Invalid token."
}
= json_encode([
[
"id" => "6wexMDE",
"token" => "78351fafe495398163fff847f9a26dda440435dcf7b5f92e8e36308f3683d771"
],
[
"id" => "OahzhMG",
"token" => "6520dd42ec3d5fd0e83f28220974fb83d3bdc0746853f5022373f8e5b062651b"
],
], JSON_PRETTY_PRINT); ?>
207,
indicating that the request was processed.
Results for the individual operations are included in the response body.
=json_encode(new MultiResponse()
->addResponse("6wexMDE", new ApiResponse())
->addResponse("OahzhMG", new ApiResponse()), JSON_PRETTY_PRINT); ?>
=json_encode(new MultiResponse()
->addResponse("6wexMDE", new ApiResponse())
->addResponse("OahzhMG", new ApiError(404, "Log not found.")), JSON_PRETTY_PRINT); ?>
{
"success": false,
"error": "No logs provided."
}
| Field | Type | Description |
|---|---|---|
| [id] | string | The log file id, received from the paste endpoint or from a URL (= htmlspecialchars(URL::getBase()->toString()); ?>/[id]). |
[18:25:33] [Server thread/INFO]: Starting minecraft server version 1.16.2 [18:25:33] [Server thread/INFO]: Loading properties [18:25:34] [Server thread/INFO]: Default game type: SURVIVAL ...
{
"success": false,
"error": "Log not found."
}
| Field | Type | Description |
|---|---|---|
| [id] | string | The log file id, received from the paste endpoint or from a URL (= htmlspecialchars(URL::getBase()->toString()); ?>/[id]). |
{
"id": "name/type",
"name": "Software name, e.g. Vanilla",
"type": "Type name, e.g. Server Log",
"version": "Version, e.g. 1.12.2",
"title": "Combined title, e.g. Vanilla 1.12.2 Server Log",
"analysis": {
"problems": [
{
"message": "A message explaining the problem.",
"counter": 1,
"entry": {
"level": 6,
"time": null,
"prefix": "The prefix of this entry, usually the part containing time and loglevel.",
"lines": [
{
"number": 1,
"content": "The full content of the line."
}
]
},
"solutions": [
{
"message": "A message explaining a possible solution."
}
]
}
],
"information": [
{
"message": "Label: value",
"counter": 1,
"label": "The label of this information, e.g. Minecraft version",
"value": "The value of this information, e.g. 1.12.2",
"entry": {
"level": 6,
"time": null,
"prefix": "The prefix of this entry, usually the part containing time and loglevel.",
"lines": [
{
"number": 6,
"content": "The full content of the line."
}
]
}
}
]
}
}
{
"success": false,
"error": "Log not found."
}
If you only want to use the analysis features of this service without saving the log, you can use this endpoint. Please do not save logs that you only want to analyse, as this wastes storage space and resources.
| Field | Type | Description |
|---|---|---|
| content | string | The raw log file content as string. Maximum length is 10MiB and 25k lines, will be shortened if necessary. |
{
"id": "name/type",
"name": "Software name, e.g. Vanilla",
"type": "Type name, e.g. Server Log",
"version": "Version, e.g. 1.12.2",
"title": "Combined title, e.g. Vanilla 1.12.2 Server Log",
"analysis": {
"problems": [
{
"message": "A message explaining the problem.",
"counter": 1,
"entry": {
"level": 6,
"time": null,
"prefix": "The prefix of this entry, usually the part containing time and loglevel.",
"lines": [
{
"number": 1,
"content": "The full content of the line."
}
]
},
"solutions": [
{
"message": "A message explaining a possible solution."
}
]
}
],
"information": [
{
"message": "Label: value",
"counter": 1,
"label": "The label of this information, e.g. Minecraft version",
"value": "The value of this information, e.g. 1.12.2",
"entry": {
"level": 6,
"time": null,
"prefix": "The prefix of this entry, usually the part containing time and loglevel.",
"lines": [
{
"number": 6,
"content": "The full content of the line."
}
]
}
}
]
}
}
{
"success": false,
"error": "Required field 'content' is empty."
}
{
"storageTime": 7776000,
"maxLength": 10485760,
"maxLines": 25000
}
| Field | Type | Description |
|---|---|---|
| storageTime | integer | The duration in seconds that a log is stored for after the last view. |
| maxLength | integer | Maximum file length in bytes. Logs over this limit will be truncated to this length. |
| maxLines | integer | Maximum number of lines. Additional lines will be removed. |
Filters modify the log content before storing it. They are applied automatically when creating a new log on the server side. You can get a list of active filters from this endpoint if you want to apply the same filters on the client side before uploading a log.
=htmlspecialchars(json_encode(\Aternos\Mclogs\Filter\Filter::getAll(), JSON_PRETTY_PRINT)); ?>
| Type | Description |
|---|---|
| trim | Trim any whitespace characters from the beginning and end of the log content. |
| limit-bytes | Limit the log content to a maximum number of bytes (data.limit). Content exceeding this limit will be truncated. |
| limit-lines | Limit the log content to a maximum number of lines (data.limit). Additional lines will be removed. |
| regex | Apply regular expression replacements to the log content. Each pattern in data.patterns will be applied in order and replaced with the provided replacement, unless the matched string matches one of the exemption patterns in data.exemptions. |
The API has currently a rate limit of 60 requests per minute per IP address. This is set to ensure the operability of this service. If you have any use case that requires a higher limit, feel free to contact us.
Paste or drop your log here