Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions knowledgebase/knowledge.csv
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
"useless for the following reason","TimeSync","Daedalus Wallet Support Issue 1 Your PC's time is out of sync","To fix this issue, user needs to synchronize your computer's time"
"DBMalformed","DBError","Daedalus Wallet Support Issue 2 Local block data is corrupted","To fix this issue, please delete the content of the DB-1.0 folder"
"signalProcess: permission denied (Operation not permitted","StaleLockFile","Daedalus Wallet Support Issue 3 Launching node without admin rights","Please make sure you launch the application with admin rights"
"No such file or directory","FileNotFound","Daedalus Wallet Support Issue 4 File missing","to fix this issue, Please reinstall Daedalus and run the application"
"resource exhausted (No space left on device)","ShortStorage","Daedalus Wallet Support Issue 5 Not enough space on hard drive to store block data","To fix this, please create more disk space on your computer"
"returned empty list","NetworkError","Daedalus Wallet Support Issue 6 Firewall is blocking the connection","To fix this issue, please try other ISP provider"
"irrelevant to given wallet","BalanceError","Daedalus Wallet Support Issue 7 Daedalus shows wrong Ada amount","Unfortunately, there's no workaround for this solution. Please report support@iohk.io immediately"
"Network.Socket.recvBuf: resource vanished","ResourceVanished","Daedalus Wallet Support Issue 8 Network error","To fix this issue, please try other ISP provider"
"IO error: Failed to create dir","UserNameError","Daedalus Wallet Support Issue 9 User is using non-latin characters for username","To fix this issue, pleae change your PC's username using only latin-characters"
"open.lock: Locked by","StaleLockFile","Daedalus Wallet Support Issue 10 open.lock file is corrupted due to improper shutdown","The issue is that the application was improperly shutdown. As a workaround, you'll need to delete open.lock file."
"Network.Socket.recvBuf: failed (No error)","ConnectionRefused","Daedalus Wallet Support Issue 11 Firewall is blocking the connection","To fix this issue, please try other ISP provider"
"The system cannot find the file specified","DBPath","Daedalus Wallet Support Issue 12 Daedalus cannot find certain files","Unfortunately, there's no workaround for this solution. Need more information"
"IO error: Can not get size for","CannotGetDBSize","Daedalus Wallet Support Issue 13 Error message of Couldn’t pack log files shows up","Unfortunately, there's no workaround for this solution. Please contact support@iohk.io"
"useless for the following reason","TimeSync","Daedalus Wallet Support Issue 1 Your PC's time is out of sync","To fix this issue, user needs to synchronize your computer's time","227"
"DBMalformed","DBError","Daedalus Wallet Support Issue 2 Local block data is corrupted","To fix this issue, please delete the content of the DB-1.0 folder","228"
"signalProcess: permission denied (Operation not permitted","StaleLockFile","Daedalus Wallet Support Issue 3 Launching node without admin rights","Please make sure you launch the application with admin rights","229"
"No such file or directory","FileNotFound","Daedalus Wallet Support Issue 4 File missing","to fix this issue, Please reinstall Daedalus and run the application","230"
"resource exhausted (No space left on device)","ShortStorage","Daedalus Wallet Support Issue 5 Not enough space on hard drive to store block data","To fix this, please create more disk space on your computer","231"
"returned empty list","NetworkError","Daedalus Wallet Support Issue 6 Firewall is blocking the connection","To fix this issue, please try other ISP provider","237"
"irrelevant to given wallet","BalanceError","Daedalus Wallet Support Issue 7 Daedalus shows wrong Ada amount","Unfortunately, there's no workaround for this solution. Please report support@iohk.io immediately","211"
"Network.Socket.recvBuf: resource vanished","ResourceVanished","Daedalus Wallet Support Issue 8 Network error","To fix this issue, please try other ISP provider","234"
"IO error: Failed to create dir","UserNameError","Daedalus Wallet Support Issue 9 User is using non-latin characters for username","To fix this issue, pleae change your PC's username using only latin-characters","235"
"open.lock: Locked by","StaleLockFile","Daedalus Wallet Support Issue 10 open.lock file is corrupted due to improper shutdown","The issue is that the application was improperly shutdown. As a workaround, you'll need to delete open.lock file.","236"
"Network.Socket.recvBuf: failed (No error)","ConnectionRefused","Daedalus Wallet Support Issue 11 Firewall is blocking the connection","To fix this issue, please try other ISP provider","234"
2 changes: 1 addition & 1 deletion log-classifier.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@ test-suite log-classifier-test
ScopedTypeVariables
UndecidableInstances
MonadFailDesugaring
TupleSections
TupleSections
29 changes: 16 additions & 13 deletions src/CLI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import Options.Applicative (Parser, ParserInfo, argument, auto, comman
progDesc, strOption, (<**>))
import Paths_log_classifier (version)

data CLI = CollectEmails -- ^ Collect email addresses
| ProcessTicket Int -- ^ Process ticket of an given ticket id
| ProcessTickets -- ^ Procss all the tickets in the Zendesk
| RawRequest String -- ^ Raw request to the given url
| ShowStatistics -- ^ Show statistics
deriving (Show)
data CLI
= CollectEmails -- ^ Collect email addresses
| ProcessTicket Int -- ^ Process ticket of an given ticket id
| ProcessTickets -- ^ Process all the tickets in Zendesk
| FetchTickets -- ^ Fetch all the tickets in Zendesk
| RawRequest String -- ^ Raw request to the given url
| ShowStatistics -- ^ Show statistics
deriving (Show)

-- | Parser for ProcessTicket
cmdProcessTicket :: Parser CLI
Expand All @@ -32,17 +34,18 @@ cmdRawRequest = RawRequest <$> strOption
-- | Parser for CLI commands
cli :: Parser CLI
cli = hsubparser $ mconcat
[
command "collect-emails" (info (pure CollectEmails)
(progDesc "Collect emails requested by single user"))
[ command "collect-emails" (info (pure CollectEmails)
(progDesc "Collect emails requested by single user"))
, command "process-tickets" (info (pure ProcessTickets)
(progDesc "Process all the tickets i.e add comments, tags."))
(progDesc "Process all the tickets i.e add comments, tags."))
, command "fetch-tickets" (info (pure FetchTickets)
(progDesc "Fetch all the tickets that need to be analyzes."))
, command "process-ticket" (info cmdProcessTicket
(progDesc "Process Zendesk ticket of an given ticket id"))
(progDesc "Process Zendesk ticket of an given ticket id"))
, command "raw-request" (info cmdRawRequest
(progDesc "Raw request to the given url"))
(progDesc "Raw request to the given url"))
, command "show-stats" (info (pure ShowStatistics)
(progDesc "Print list of ticket Ids that agent has been assigned"))
(progDesc "Print list of ticket Ids that agent has been assigned"))
]

-- | Get CLI arguments from command line
Expand Down
59 changes: 45 additions & 14 deletions src/LogAnalysis/Classifier.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ module LogAnalysis.Classifier
( extractErrorCodes
, extractIssuesFromLogs
, prettyFormatAnalysis
, prettyFormatNoIssues
, prettyFormatLogReadError
) where

import Universum

import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map.Strict as Map
import Data.Text.Encoding.Error (ignore)
import Data.Text.Lazy (isInfixOf)
import Data.Text (isInfixOf)

import LogAnalysis.Types (Analysis, Knowledge (..), renderErrorCode)

Expand All @@ -38,7 +40,7 @@ analyzeLine analysis str = Map.mapWithKey (compareWithKnowledge str) analysis
-- | Compare the line with knowledge lists
compareWithKnowledge :: LText -> Knowledge -> [ LText ] -> [ LText ]
compareWithKnowledge str Knowledge{..} xs =
if kErrorText `isInfixOf` str
if kErrorText `isInfixOf` (show str)
then str : xs
else xs

Expand All @@ -53,16 +55,45 @@ filterAnalysis as = do
extractErrorCodes :: Analysis -> [ Text ]
extractErrorCodes as = map (\(Knowledge{..}, _) -> renderErrorCode kErrorCode) $ Map.toList as

-- | TODO (Hiroto): Format the text in better way
prettyFormatAnalysis :: Analysis -> LText
prettyHeader :: Text
prettyHeader =
"Dear user," <>
"\n" <>
"\n" <>
"Thank you for contacting the IOHK Technical Support Desk. We appologize for the delay in responding to you. " <>
"\n"

prettyFooter :: Text
prettyFooter =
"\n" <>
"Please be patient since we have a large number of such requests to respond to. We will respond as soon as we can, but in the meantime, if you want to check the status of your ticket you can do so here." <>
"\n" <>
"Please let us know if your issue is resolved. If you are still having trouble please reply back to this email and attach a new log file so that we can work with you to fix your problem." <>
"\n" <>
"Thanks, " <>
"\n" <>
"The IOHK Technical Support Desk Team" <>
"\n"

-- | We need to fix this, this will pick the last issue found.
prettyFormatAnalysis :: Analysis -> Text
prettyFormatAnalysis as =
let aList = Map.toList as
in foldr (\(Knowledge{..}, txts) acc ->
"\n" <> show kErrorCode
<> "\n" <> kProblem
<> "\n **" <> kSolution
<> "** \n"
<> foldr1 (\txt ts -> "\n" <> txt <> "\n" <> ts) txts -- List errors
<> "\n" <> acc
<> "\n\n"
) "" aList
prettyHeader <>
show foundIssues <>
prettyFooter
where
foundIssues = foldr (\(Knowledge{..}, _) acc -> acc <> foundIssuesTemplate kFAQNumber) "" $ Map.toList as
foundIssuesTemplate kFAQNumber = "\n" <> "We have analyzed the log that you submitted and it appears that your issue is addressed in the Daedalus FAQ in Issue " <> kFAQNumber <> ". Please go to https://daedaluswallet.io/faq/ and check Issue " <> kFAQNumber <> " to resolve your problem." <> "\n\n"

prettyFormatNoIssues :: Text
prettyFormatNoIssues =
prettyHeader <>
"We have analyzed the log that you submitted and it appears that you do not have an identifiable technical issue." <>
prettyFooter

prettyFormatLogReadError :: Text
prettyFormatLogReadError =
prettyHeader <>
"We tried to analyze the log that you submitted and it appears that your log cannot be processed. Please try attaching the log file once again in the agreed format." <>
prettyFooter

49 changes: 28 additions & 21 deletions src/LogAnalysis/KnowledgeCSVParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,26 @@ module LogAnalysis.KnowledgeCSVParser

import Universum

import Data.Attoparsec.Text.Lazy as ALT
import qualified Data.Text.Lazy as LT
import Data.Attoparsec.Text (Parser, char, endOfLine, takeTill, string)

import LogAnalysis.Types (ErrorCode (..), Knowledge (..))

-- | Take any string that is inside quotes
insideQuotes :: Parser LText
insideQuotes =
LT.append <$> (LT.fromStrict <$> ALT.takeWhile (/= '"'))
<*> (LT.concat <$> many (LT.cons <$> dquotes <*> insideQuotes))
<?> "inside of double quotes"
where
dquotes :: Parser Char
dquotes = string "\"\"" >> return '"'
<?> "paired double quotes"

-- | Parse quoted field
quotedField :: Parser LText
quotedField =
char '"' *> insideQuotes <* char '"'
<?> "quoted field"
{-

stack ghci
fContent <- readFile "./knowledgebase/knowledge.csv"
parseOnly parseKnowLedgeBase fContent

-}

-- | Parse quoted text field
quotedText :: Parser Text
quotedText = do
_ <- char '"'
result <- takeTill (=='\"')
_ <- char '"'
pure result

--- | Parse ErrorCode
parseErrorCode :: Parser ErrorCode
Expand All @@ -49,16 +48,24 @@ parseErrorCode =
-- | Parse each csv records
parseKnowledge :: Parser Knowledge -- not really clean code..
parseKnowledge = do
e <- quotedField
e <- quotedText
_ <- char ','
_ <- char '"'
c <- parseErrorCode
_ <- char '"'
_ <- char ','
p <- quotedField
p <- quotedText
_ <- char ','
s <- quotedText
_ <- char ','
s <- quotedField
return $ Knowledge e c p s
f <- quotedText
return $ Knowledge
{ kErrorText = e
, kErrorCode = c
, kProblem = p
, kSolution = s
, kFAQNumber = f
}

-- | Parse CSV file and create knowledgebase
parseKnowLedgeBase :: Parser [ Knowledge ]
Expand Down
8 changes: 5 additions & 3 deletions src/LogAnalysis/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ data ErrorCode

-- | Record identifying the issue
data Knowledge = Knowledge
{ kErrorText :: !LText
{ kErrorText :: !Text
-- ^ Text used for matching error lines
, kErrorCode :: !ErrorCode
-- ^ Identity for error code
, kProblem :: !LText
, kProblem :: !Text
-- ^ Text describing what is the problem
, kSolution :: !LText
, kSolution :: !Text
-- ^ Text describing how to solve the issue
, kFAQNumber :: !Text
-- ^ The FAQ number that will be displayed on the official Cardano FAQ page
} deriving (Show)

renderErrorCode :: ErrorCode -> Text
Expand Down
63 changes: 37 additions & 26 deletions src/Types.hs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
{-# LANGUAGE OverloadedStrings #-}

module Types
( Attachment(..)
, Comment(..)
, CommentOuter(..)
, Ticket(..)
, TicketInfo(..)
, TicketId
, TicketList(..)
, TicketStatus(..)
, parseAgentId
, parseComments
, parseTickets
, renderTicketStatus
) where
( ZendeskResponse (..)
, Comment(..)
, CommentOuter(..)
, Attachment(..)
, Ticket(..)
, TicketList(..)
, TicketId
, TicketInfo(..)
, TicketTag(..)
, parseAgentId
, parseComments
, parseTickets
, renderTicketStatus
) where

import Universum

Expand All @@ -32,6 +33,13 @@ data Attachment = Attachment
-- ^ Attachment size
}

-- | The response for ZenDesk.
data ZendeskResponse = ZendeskResponse
{ zrComment :: Text
, zrTags :: [Text] -- TODO(ks): This should be wrapped
, zrIsPublic :: Bool
}

-- | Comments
data Comment = Comment
{ cBody :: !Text
Expand All @@ -49,7 +57,7 @@ newtype CommentOuter = CommentOuter {
coComment :: Comment
}

-- | Zendexk ticket
-- | Zendesk ticket
data Ticket = Ticket
{ tComment :: !Comment
-- ^ Ticket comment
Expand All @@ -70,20 +78,18 @@ data TicketList = TicketList
type TicketId = Int

data TicketInfo = TicketInfo
{ tiId :: !Int
-- ^ Id of an ticket
, tiTags :: ![Text]
-- ^ Tags associated with ticket
}
{ ticketId :: !TicketId -- ^ Id of an ticket
, ticketTags :: ![Text] -- ^ Tags associated with ticket
, ticketStatus :: !Text -- ^ The status of the ticket
} deriving (Eq)

-- | Ticket status
data TicketStatus = AnalyzedByScript
-- ^ Ticket has been analyzed
| NoKnownIssue
-- ^ Ticket had no known issue
-- | Ticket tag
data TicketTag
= AnalyzedByScript -- ^ Ticket has been analyzed
| NoKnownIssue -- ^ Ticket had no known issue

-- | Defining it's own show instance to use it as tags
renderTicketStatus :: TicketStatus -> Text
renderTicketStatus :: TicketTag -> Text
renderTicketStatus AnalyzedByScript = "analyzed-by-script"
renderTicketStatus NoKnownIssue = "no-known-issues"

Expand Down Expand Up @@ -115,7 +121,12 @@ instance ToJSON Attachment where
object [ "content_url" .= url, "content_type" .= contenttype, "size" .= size]

instance FromJSON TicketInfo where
parseJSON = withObject "ticket" $ \o -> TicketInfo <$> (o .: "id") <*> (o .: "tags")
parseJSON = withObject "ticket" $ \o -> do
ticketId <- o .: "id"
ticketTags <- o .: "tags"
ticketStatus <- o .: "status"

pure TicketInfo{..}

instance FromJSON TicketList where
parseJSON = withObject "ticketList" $ \o -> TicketList <$> o .: "tickets" <*> o .: "next_page"
Expand Down
1 change: 1 addition & 0 deletions src/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import qualified Codec.Archive.Zip as Zip
import qualified Data.Map.Strict as Map

-- | Extract log file from given zip file
-- TODO(ks): What happens with the other files? We just ignore them?
extractLogsFromZip :: Int -> LByteString -> Either Text [LByteString]
extractLogsFromZip numberOfFiles file = do
zipMap <- readZip file -- Read File
Expand Down
Loading