diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..01c9646 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,27 @@ +name: Docker Image CI + +on: + workflow_dispatch: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + - name: Publish Docker Image + # You may pin to the exact commit or the version. + # uses: elgohr/Publish-Docker-Github-Action@191af57e15535d28b83589e3b5f0c31e76aa8733 + uses: elgohr/Publish-Docker-Github-Action@3.04 + with: + # The name of the image you would like to push + name: surdaft/minecraft-exporter + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c1bada --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# for testing +world diff --git a/README.md b/README.md index f878fa5..d21568e 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ # minecraft-exporter -this is a prometheus minecraft exporter +This is a prometheus minecraft exporter + This exporter reads minecrafts nbt files, the advancements files and can optionally connect via RCON to your minecraft server. -to use it mount your world to /world in the container +To use it mount your world to /world in the container -rcon connection is used to get online Players +RCON connection is used to get online Players On Forge Servers enable FORGE_SERVER to get tps information On Paper Servers enable PAPER_SERVER to get tps information -to enable rcon on your minecraft server add the following to the server.properties file: +To enable rcon on your minecraft server add the following to the server.properties file: ``` broadcast-rcon-to-ops=false @@ -18,8 +19,22 @@ rcon.password=Password enable-rcon=true ``` -The RCON Module is only enabled if `RCON_HOST` and `RCON_PASSWORD` is set +> Note: Broadcast RCON to ops is disabled, to avoid ops receiving spam whilst ingame. +--- + +# Environment Variables + +| Name | Default | Description | +| ------------- | ------- | ------------------------------------------------- | +| RCON_HOST | `None` | Host of the RCON server | +| RCON_PORT | `None` | Port RCON is hosted on | +| RCON_PASSWORD | `None` | RCON Password for access | +| HTTP_PORT | `8000` | Port to host on, in case of using outside docker* | + +> * Or other cases where you have limited control of port mappings, eg Pterodactyl. + +--- # Usage @@ -59,7 +74,9 @@ player_used_crafting_table player_quests_finished # support for betterquesting mc_custom # for 1.15 ``` -the following Metrics are only exported if RCON is configured: + +The following Metrics are only exported if RCON is configured: + ``` dim_tps dim_ticktime @@ -68,7 +85,7 @@ overall_ticktime player_online ``` -the following Metrics are exposed if Dynmap Support is enabled: +The following Metrics are exposed if Dynmap Support is enabled: ``` dynmap_tile_render_statistics @@ -76,7 +93,7 @@ dynmap_chunk_loading_statistics_count dynmap_chunk_loading_statistics_duration ``` -the following Metrics are exposed if PAPER_SERVER is enabled: +The following Metrics are exposed if PAPER_SERVER is enabled: ``` tps_1m tps_5m diff --git a/docker-compose.yaml b/docker-compose.yaml index cb439b4..a7b1c74 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,8 @@ version: '3.1' services: minecraft-exporter: - image: 'joshi425/minecraft_exporter' + build: + context: . environment: RCON_HOST: RCON_PORT: @@ -9,4 +10,4 @@ services: ports: - 9700:8000 volumes: - - /path/to/minecraft/world:/world:ro + - ./world:/world:ro diff --git a/egg-minecraft-prom-exporter.json b/egg-minecraft-prom-exporter.json new file mode 100644 index 0000000..3db4a8f --- /dev/null +++ b/egg-minecraft-prom-exporter.json @@ -0,0 +1,70 @@ +{ + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v1", + "update_url": null + }, + "exported_at": "2022-02-21T08:57:54+00:00", + "name": "Minecraft Prom Exporter", + "author": "jack.stupple@protonmail.com", + "description": "Minecraft Prom Exporter", + "features": null, + "images": [ + "joshi425\/minecraft_exporter", + "ghcr.io\/joshi425\/minecraft-exporter:latest", + "ghcr.io\/surdaft\/minecraft-exporter:latest" + ], + "file_denylist": [], + "startup": "python3 minecraft_exporter.py", + "config": { + "files": "{}", + "startup": "{\r\n \"done\": \"Exporter started on Port\"\r\n}", + "logs": "{}", + "stop": "^C" + }, + "scripts": { + "installation": { + "script": null, + "container": "alpine:3.4", + "entrypoint": "ash" + } + }, + "variables": [ + { + "name": "RCON Host", + "description": "Host of the minecraft server", + "env_variable": "RCON_HOST", + "default_value": "host.docker.internal", + "user_viewable": false, + "user_editable": false, + "rules": "string|max:32" + }, + { + "name": "RCON Port", + "description": "Port of minecraft server RCON", + "env_variable": "RCON_PORT", + "default_value": "25575", + "user_viewable": false, + "user_editable": false, + "rules": "numeric|min:0|max:35000" + }, + { + "name": "RCON Password", + "description": "Password for minecraft server RCON", + "env_variable": "RCON_PASSWORD", + "default_value": "", + "user_viewable": false, + "user_editable": false, + "rules": "string|min:0" + }, + { + "name": "HTTP Port", + "description": "Port to host metric server on", + "env_variable": "HTTP_PORT", + "default_value": "8000", + "user_viewable": false, + "user_editable": false, + "rules": "numeric|min:0|max:35000" + } + ] +} diff --git a/minecraft_exporter.py b/minecraft_exporter.py index 2c992b7..a4fb0f5 100644 --- a/minecraft_exporter.py +++ b/minecraft_exporter.py @@ -322,9 +322,11 @@ class MinecraftCollector(object): elif stat == "minecraft:damage_taken": damage_taken.add_sample('damage_taken', value=value, labels={'player': name}) elif stat == "minecraft:damage_dealt": - damage_dealt.add_sample('damage_dealt', value=value, labels={'player': name}) - elif stat == "minecraft:play_one_minute": - player_playtime.add_sample('player_playtime', value=value, labels={'player': name}) + damage_dealt.add_sample('damage_dealt',value=value,labels={'player':name}) + elif stat == "minecraft:play_time": + player_playtime.add_sample('player_playtime',value=value,labels={'player':name}) + elif stat == "minecraft:play_one_minute": # pre 1.17 + player_playtime.add_sample('player_playtime',value=value,labels={'player':name}) elif stat == "minecraft:walk_one_cm": cm_traveled.add_sample("cm_traveled", value=value, labels={'player': name, 'method': "walking"}) elif stat == "minecraft:walk_on_water_one_cm": @@ -368,11 +370,15 @@ class MinecraftCollector(object): yield metric -if __name__ == '__main__': - collector = MinecraftCollector() - start_http_server(8000) - REGISTRY.register(collector) - print("Exporter started on Port 8000") + HTTP_PORT = int(os.environ.get('HTTP_PORT')) + if HTTP_PORT == None: + HTTP_PORT = 8000 + + start_http_server(HTTP_PORT) + REGISTRY.register(MinecraftCollector()) + + print(f'Exporter started on Port {HTTP_PORT}') + while True: try: time.sleep(1)