Skip to content

Commit

Permalink
Add optimizations and setting to retry failed Plex requests (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
axsuul authored Nov 13, 2023
1 parent fafd9df commit 7fce396
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ jobs:
echo 'EOF' >> $GITHUB_ENV
# Only build and push Docker images for releases
- name: Build and push Docker image to GitHub Container Registry
uses: docker/build-push-action@v2
if: ${{ github.event_name == 'release' }}
with:
context: .
push: true
Expand All @@ -65,6 +67,7 @@ jobs:
cache-to: type=local,dest=/tmp/.buildx-cache-new

- name: Update Docker buildx cache
if: ${{ github.event_name == 'release' }}
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ These environment variables can be passed into the container (defaults are in pa
- Plex Media Server token
* `PLEX_TIMEOUT` (`10`)
- How long to wait for Plex Media Server to respond
* `PLEX_RETRIES_COUNT` (`0`)
- How many times to retry failed Plex Media Server requests
* `METRICS_PREFIX` (`plex`)
- What to prefix metric names with
* `METRICS_MEDIA_COLLECTING_INTERVAL_SECONDS` (`300`)
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ services:
# Can be set in .env
- PLEX_ADDR=${PLEX_ADDR}
- PLEX_TOKEN=${PLEX_TOKEN}
- PLEX_TIMEOUT=${PLEX_TIMEOUT}
- PLEX_RETRIES_COUNT=${PLEX_RETRIES_COUNT}
- METRICS_MEDIA_COLLECTING_INTERVAL_SECONDS=300
volumes:
- .:/srv:delegated
Expand Down
66 changes: 52 additions & 14 deletions lib/middleware/collector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ def initialize(app)

# Plex configs
@plex_addr = ENV["PLEX_ADDR"] || "http://localhost:32400"
@plex_token = ENV["PLEX_TOKEN"]
@plex_timeout = ENV["PLEX_TIMEOUT"]&.to_i || 10
@plex_retries_count = ENV["PLEX_RETRIES_COUNT"]&.to_i || 0

# Metrics configs
@metrics_prefix = ENV["METRICS_PREFIX"] || "plex"
Expand Down Expand Up @@ -54,21 +56,32 @@ def initialize(app)
end

def call(env)
case env["PATH_INFO"]
when "/metrics"
collect_metrics
end

@app.call(env)
end

def collect_metrics
log(step: "collect_metrics")

begin
capabilities_resource = send_plex_api_request(method: :get, endpoint: "/").dig("MediaContainer")
capabilities_resource = send_plex_api_request(method: :get, endpoint: "/identity").dig("MediaContainer")
metric_up_value = 1

log(plex_up: true)

set_gauge_metric_values_or_reset_missing(
metric: @metrics[:info],
values: {
{ version: capabilities_resource.dig("version") } => 1,
},
)

collect_session_metrics
collect_activity_metrics
collect_media_metrics
rescue HTTP::Error
log(plex_up: false)

# Value of 0 means there's no heartbeat
metric_up_value = 0
ensure
Expand All @@ -80,11 +93,23 @@ def call(env)
)
end

@app.call(env)
[
-> { collect_session_metrics },
-> { collect_activity_metrics },
-> { collect_media_metrics },
].each do |collection|
collection.call
rescue HTTP::Error
# Skip if it errors out
end
end

private

def log(**labels)
puts(labels.to_a.map { |k, v| "#{k}=#{v}" }.join(" "))
end

def collect_activity_metrics
values = Hash.new { |h, k| h[k] = 0 }

Expand Down Expand Up @@ -203,15 +228,28 @@ def fetch_media_section_count(key:, params: {}, **options)
end

def send_plex_api_request(method:, endpoint:, **options)
response = HTTP
.timeout(@plex_timeout)
.headers(
"X-Plex-Token" => ENV["PLEX_TOKEN"],
"Accept" => "application/json",
)
.public_send(method, "#{@plex_addr}#{endpoint}", **options)
retries_count = 0

JSON.parse(response)
# Keep trying request if it fails until number of retries have been exhausted
loop do
url = "#{@plex_addr}#{endpoint}"

log(method: method, url: url)

response = HTTP
.timeout(@plex_timeout)
.headers(
"X-Plex-Token" => @plex_token,
"Accept" => "application/json",
)
.public_send(method, url, **options)

return JSON.parse(response)
rescue HTTP::Error => e
raise(e) if retries_count >= @plex_retries_count

retries_count += 1
end
end

# Set metric values and reset all other labels that werenn't passed in
Expand Down

0 comments on commit 7fce396

Please sign in to comment.