Add very early attempt at retrieving IP address per stream.

This commit is contained in:
Tim 2015-07-06 00:45:42 +02:00
parent 9d5dabca14
commit 7a5cad1a31
5 changed files with 125 additions and 34 deletions

View file

@ -18,7 +18,7 @@ import re
import os
import plexpy
def get_log_tail(window=20):
def get_log_tail(window=20, parsed=True):
if plexpy.CONFIG.PMS_LOGS_FOLDER:
log_file = os.path.join(plexpy.CONFIG.PMS_LOGS_FOLDER, 'Plex Media Server.log')
@ -33,24 +33,27 @@ def get_log_tail(window=20):
log_lines = tail(logfile, window)
line_error = False
clean_lines = []
for i in log_lines:
try:
log_time = i.split(' [')[0]
log_level = i.split('] ', 1)[1].split(' - ',1)[0]
log_msg = i.split('] ', 1)[1].split(' - ',1)[1]
full_line = [log_time, log_level, log_msg]
clean_lines.append(full_line)
except:
line_error = True
full_line = ['', '', 'Unable to parse log line.']
clean_lines.append(full_line)
if parsed:
line_error = False
clean_lines = []
for i in log_lines:
try:
log_time = i.split(' [')[0]
log_level = i.split('] ', 1)[1].split(' - ',1)[0]
log_msg = i.split('] ', 1)[1].split(' - ',1)[1]
full_line = [log_time, log_level, log_msg]
clean_lines.append(full_line)
except:
line_error = True
full_line = ['', '', 'Unable to parse log line.']
clean_lines.append(full_line)
if line_error:
logger.error('PlexPy was unable to parse some lines of the Plex Media Server log.')
if line_error:
logger.error('PlexPy was unable to parse some lines of the Plex Media Server log.')
return clean_lines
return clean_lines
return log_lines
# http://stackoverflow.com/a/13790289/2405162
def tail(f, lines=1, _buffer=4098):

View file

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from plexpy import logger, helpers, plexwatch, pmsconnect, notification_handler, config
from plexpy import logger, helpers, plexwatch, pmsconnect, notification_handler, config, log_reader
from xml.dom import minidom
from httplib import HTTPSConnection
@ -23,6 +23,8 @@ import os
import sqlite3
import threading
import plexpy
import re
import time
monitor_lock = threading.Lock()
@ -32,6 +34,7 @@ def check_active_sessions():
pms_connect = pmsconnect.PmsConnect()
session_list = pms_connect.get_current_activity()
monitor_db = MonitorDatabase()
# logger.debug(u"Checking for active streams.")
if session_list['stream_count'] != '0':
media_container = session_list['sessions']
@ -46,6 +49,7 @@ def check_active_sessions():
title = session['title']
parent_title = session['parent_title']
grandparent_title = session['grandparent_title']
machine_id = session['machine_id']
write_session = monitor_db.write_session_key(session_key, rating_key, media_type)
if write_session == 'insert':
@ -60,6 +64,12 @@ def check_active_sessions():
pushmessage = '%s (%s) starting playing %s' % (friendly_name, platform, item_title)
notification_handler.push_nofitications(pushmessage, 'PlexPy Playback started', 'Playback Started')
# Try and grab IP address from logs
if plexpy.CONFIG.PMS_LOGS_FOLDER:
monitor_processing = MonitorProcessing()
ip_address = monitor_processing.find_session_ip(rating_key=rating_key,
machine_id=machine_id)
keys = {'session_key': session_key,
'rating_key': rating_key}
active_streams.append(keys)
@ -186,3 +196,54 @@ class MonitorDatabase(object):
# We want to know if it was an update or insert
return trans_type
class MonitorProcessing(object):
def __init__(self):
pass
def find_session_ip(self, rating_key=None, machine_id=None):
logger.debug(u"Requesting log lines...")
log_lines = log_reader.get_log_tail(window=5000, parsed=False)
rating_key_line = 'metadata%2F' + rating_key
machine_id_line = 'session=' + machine_id
for line in reversed(log_lines):
# We're good if we find a line with both machine id and rating key
# This is usually when there is a transcode session
if machine_id_line in line and rating_key_line in line:
# Currently only checking for ipv4 addresses
ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}', line)
if ipv4:
# The logged IP will always be the first match and we don't want localhost entries
if ipv4[0] != '127.0.0.1':
logger.debug(u"Matched IP address (%s) for stream ratingKey %s and machineIdentifier %s."
% (ipv4[0], rating_key, machine_id))
return ipv4[0]
logger.debug(u"Unable to find IP address on first pass. Attempting fallback check in 5 seconds...")
# Wait for the log to catch up and read in new lines
time.sleep(5)
logger.debug(u"Requesting log lines...")
log_lines = log_reader.get_log_tail(window=5000, parsed=False)
for line in reversed(log_lines):
if 'GET /:/timeline' in line and rating_key_line in line:
# Currently only checking for ipv4 addresses
# This method can return the wrong IP address if more than one user
# starts watching the same media item around the same time.
ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}', line)
if ipv4:
# The logged IP will always be the first match and we don't want localhost entries
if ipv4[0] != '127.0.0.1':
logger.debug(u"Matched IP address (%s) for stream ratingKey %s." % (ipv4[0], rating_key))
return ipv4[0]
logger.debug(u"Unable to find IP address on fallback search. Not logging IP address.")
return None

View file

@ -24,7 +24,7 @@ class PmsConnect(object):
"""
def __init__(self):
self.protocol = 'HTTPS'
self.protocol = 'HTTP'
self.request_handler = http_handler.HTTPHandler(host=plexpy.CONFIG.PMS_IP,
port=plexpy.CONFIG.PMS_PORT,
token=plexpy.CONFIG.PMS_TOKEN)
@ -196,7 +196,7 @@ class PmsConnect(object):
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
output = {'recently_added': None}
output = {'recently_added': []}
return output
if a.getElementsByTagName('Directory'):
@ -459,14 +459,24 @@ class PmsConnect(object):
duration = helpers.get_xml_attr(media_info, 'duration')
progress = helpers.get_xml_attr(session, 'viewOffset')
user_details = plex_watch.get_user_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Track'):
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')[:-6]
else:
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'art': helpers.get_xml_attr(session, 'art'),
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'thumb': helpers.get_xml_attr(session, 'thumb'),
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'friendly_name': plex_watch.get_user_friendly_name(
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'machine_id': machine_id,
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
@ -528,15 +538,25 @@ class PmsConnect(object):
thumb = helpers.get_xml_attr(session, 'thumb')
use_indexes = 0
user_details = plex_watch.get_user_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Video'):
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')[:-6]
else:
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
if helpers.get_xml_attr(session, 'type') == 'episode':
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'art': helpers.get_xml_attr(session, 'art'),
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'thumb': thumb,
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'friendly_name': plex_watch.get_user_friendly_name(
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'machine_id': machine_id,
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
@ -561,9 +581,11 @@ class PmsConnect(object):
'thumb': thumb,
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'friendly_name': plex_watch.get_user_friendly_name(
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'machine_id': machine_id,
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
@ -588,9 +610,11 @@ class PmsConnect(object):
'thumb': thumb,
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'friendly_name': plex_watch.get_user_friendly_name(
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'machine_id': machine_id,
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),

View file

@ -952,4 +952,4 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json'
return result
else:
logger.warn('Unable to retrieve data.')
logger.warn('Unable to retrieve data.')