Skip to content
Browse files

Enable Papertrail logging, fixes #125.

Adds a preference to the logging screen for enabling remote logging. When
enabled, it turns on remote logging for 20 minutes and enables the remote
logging on the primary PMS for that same duration. All log messages will
be passed along to Papertrail, and everything will be sent at debug.
  • Loading branch information...
1 parent 336ea13 commit 7261c6d8c8a1c2ffe989ba24298d11d784b62025 @sullman sullman committed
Showing with 94 additions and 3 deletions.
  1. +78 −0 Plex/source/LogUtils.brs
  2. +5 −1 Plex/source/MyPlexManager.brs
  3. +11 −2 Plex/source/PreferenceScreen.brs
View
78 Plex/source/LogUtils.brs
@@ -25,6 +25,9 @@ Function createLogger() As Object
logger.Disable = loggerDisable
logger.Flush = loggerFlush
+ logger.EnablePapertrail = loggerEnablePapertrail
+ logger.LogToPapertrail = loggerLogToPapertrail
+
GetGlobalAA().AddReplace("logger", logger)
' TODO(schuyler): Especially if we ever want a web server for something
@@ -66,6 +69,20 @@ Sub loggerLog(msg)
if m.DebugBuffer.Len() > 8192 then
m.Flush()
end if
+
+ ' Check on papertrail logging. If it's enabled, we need to make sure
+ ' time hasn't elapsed yet, and then log the message.
+
+ if m.RemoteLoggingTimer <> invalid then
+ if m.RemoteLoggingTimer.TotalSeconds() > m.RemoteLoggingSeconds then
+ m.SyslogSocket.Close()
+ m.SyslogSocket = invalid
+ m.SyslogPackets = invalid
+ m.RemoteLoggingTimer = invalid
+ else
+ m.LogToPapertrail(msg)
+ end if
+ end if
End Sub
Sub loggerEnable()
@@ -186,3 +203,64 @@ Function ProcessLogsRequest() As Boolean
return true
End Function
+Sub loggerEnablePapertrail(minutes=20, pms=invalid)
+ myPlex = GetGlobalAA().Lookup("myplex")
+ if myPlex = invalid OR NOT myPlex.IsSignedIn then return
+
+ ' Create the remote syslog socket
+
+ port = CreateObject("roMessagePort")
+ addr = CreateObject("roSocketAddress")
+ udp = CreateObject("roDatagramSocket")
+
+ ' We're never going to wait on this message port, but we still need to
+ ' set it to make the socket async.
+ udp.setMessagePort(port)
+
+ addr.setHostname("logs.papertrailapp.com")
+ addr.setPort(60969)
+ udp.setSendToAddress(addr)
+
+ m.SyslogSocket = udp
+ m.SyslogPackets = CreateObject("roList")
+
+ m.RemoteLoggingSeconds = minutes * 60
+ m.RemoteLoggingTimer = CreateObject("roTimespan")
+
+ ' We always need to send a myPlex username, so cache the username now. If
+ ' the user happens to disconnect the myPlex account while remote logging is
+ ' enabled, the logs will continue to be associated with the original
+ ' account.
+
+ m.SyslogHeader = "<135> PlexForRoku: [" + myPlex.Username + "] "
+
+ ' Enable papertrail logging for the PMS, too.
+ if pms <> invalid then
+ pms.ExecuteCommand("/log/networked?minutes=" + tostr(minutes))
+ end if
+End Sub
+
+Sub loggerLogToPapertrail(msg)
+ ' Just about the simplest syslog packet possible without being empty.
+ ' We're using the local0 facility and logging everything as debug, so
+ ' <135>. We simply skip the timestamp and hostname, the receiving
+ ' timestamp will be used and is good enough to avoid writing strftime
+ ' in brightscript. Then we hardcode PlexForRoku as the TAG field and
+ ' include the myPlex username in the CONTENT. Finally, we make sure
+ ' the whole thing isn't too long.
+
+ bytesLeft = 1024 - Len(m.SyslogHeader)
+ if bytesLeft > Len(msg) then
+ packet = m.SyslogHeader + msg
+ else
+ packet = m.SyslogHeader + Left(msg, bytesLeft)
+ end if
+
+ m.SyslogPackets.AddTail(packet)
+
+ ' If we have anything backed up, try to send it now.
+ while m.SyslogSocket.isWritable() AND m.SyslogPackets.Count() > 0
+ m.SyslogSocket.sendStr(m.SyslogPackets.RemoveHead())
+ end while
+End Sub
+
View
6 Plex/source/MyPlexManager.brs
@@ -54,6 +54,9 @@ Function createMyPlexManager(viewController) As Object
obj.TranscodeServer = invalid
obj.CheckTranscodeServer = mpCheckTranscodeServer
+ ' Stash a copy in the global AA
+ GetGlobalAA().AddReplace("myplex", obj)
+
return obj
End Function
@@ -170,11 +173,12 @@ Function mpValidateToken(token) As Boolean
if type(event) = "roUrlEvent" AND event.GetInt() = 1 AND event.GetResponseCode() = 201 then
xml = CreateObject("roXMLElement")
xml.Parse(event.GetString())
+ m.Username = xml.username.GetText()
m.EmailAddress = xml.email.GetText()
m.IsSignedIn = true
m.AuthToken = token
- Debug("Validated myPlex token, corresponds to " + tostr(m.EmailAddress))
+ Debug("Validated myPlex token, corresponds to " + tostr(m.Username))
else
Debug("Failed to validate myPlex token")
m.IsSignedIn = false
View
13 Plex/source/PreferenceScreen.brs
@@ -176,8 +176,7 @@ Function createPreferencesScreen(viewController) As Object
default: "random"
}
- ' This is a slightly evil amount of reaching inside another object...
- obj.myplex = viewController.Home.myplex
+ obj.myplex = GetGlobalAA().Lookup("myplex")
return obj
End Function
@@ -546,6 +545,12 @@ Sub debugRefreshItems()
if m.Logger.Enabled then
m.AddItem({title: "Disable Logging"}, "disable")
+
+ myPlex = GetGlobalAA().Lookup("myplex")
+ if myPlex <> invalid AND myPlex.IsSignedIn then
+ m.AddItem({title: "Enable Remote Logging"}, "remote")
+ end if
+
m.AddItem({title: "Download Logs"}, "download")
else
m.AddItem({title: "Enable Logging"}, "enable")
@@ -579,6 +584,10 @@ Sub showDebugLoggingScreen()
screen = createLogDownloadScreen(m.ViewController)
screen.Show()
screen = invalid
+ else if command = "remote" then
+ ' TODO(schuyler) What if we want to debug something related
+ ' to a non-primary server?
+ m.Logger.EnablePapertrail(20, GetPrimaryServer())
else if command = "close" then
m.Screen.Close()
end if

0 comments on commit 7261c6d

Please sign in to comment.
Something went wrong with that request. Please try again.