nri-prelude-0.1.0.0: A Prelude inspired by the Elm programming language

Safe HaskellNone
LanguageHaskell2010

Log

Contents

Description

This module is dedicated to logging information in production, to help understand what the application is doing when something goes wrong. This sets it apart from the Debug module which provide helpers for debugging problems in development.

This module does not have an Elm counterpart.

Synopsis

Logging

info :: HasCallStack => Text -> [Context] -> Task e () Source #

A log message useful for when things have gone off the rails. We should have a ton of messages at this level. It should help us out when we're dealing with something hard.

In addition to a log message you can pass additional key-value pairs with information that might be relevant for debugging.

info "I added 1 and 1" [context "answer" 2]

userIsAnnoyed :: HasCallStack => Text -> Text -> [Context] -> Task e () Source #

A log message when the user is annoyed, but not blocked.

Log.userIsAnnoyed "We poked the user unnecessarily." "Try to stop poking the user." [ Log.context "The type of poking stick" poker ]

userIsConfused :: HasCallStack => Text -> Text -> [Context] -> Task e () Source #

Like userIsAnnoyed, but when the user is userIsConfused.

userIsPained :: HasCallStack => Text -> Text -> [Context] -> Task e () Source #

Like userIsAnnoyed, but when the user is in pain.

userIsBlocked :: HasCallStack => Text -> Text -> [Context] -> Task e () Source #

Like userIsAnnoyed, but when the user is blocked.

withContext :: HasCallStack => Text -> [Context] -> Task e b -> Task e b Source #

Mark a block of code as a logical unit by giving it a name. This name will be used in logs and monitoring dashboards, so use this function to help debug production problems.

In addition to a name you can pass this function a list of context. A context is a key-value pair you want to attach to all logs made inside of the block of code wrapped.

Example usage:

withContext "play-music" [context "artist" "The Beatles"] <| do -- your code here!

Additionally, this function adds an entry to our homemade stack trace for if something errors. Why not use the built-in stack trace? Well, the built-in stack trace only records a frame if you add Stack.HasCallStack => to the function, so if we want a full stack trace, we need to add that to literally all functions. Instead of doing that, we will use withContext to collect the stack trace, since it is used fairly often already. It will not be complete either, but it's the best we can do without too much trouble.

context :: ToJSON a => Text -> a -> Context Source #

A key-value pair that can be added to a log context. All log expressions within the context will always log this key-value pair.

Secrets

data Secret a Source #

Distinguishes data that is secret and should not be logged.

Please be careful when defining or altering instances for this data type. There's a good chance we will leak credentials, PII, or other equally sensitive information.

Instances
Functor Secret Source # 
Instance details

Defined in Log

Methods

fmap :: (a -> b) -> Secret a -> Secret b #

(<$) :: a -> Secret b -> Secret a #

Applicative Secret Source # 
Instance details

Defined in Log

Methods

pure :: a -> Secret a #

(<*>) :: Secret (a -> b) -> Secret a -> Secret b #

liftA2 :: (a -> b -> c) -> Secret a -> Secret b -> Secret c #

(*>) :: Secret a -> Secret b -> Secret b #

(<*) :: Secret a -> Secret b -> Secret a #

Eq a => Eq (Secret a) Source # 
Instance details

Defined in Log

Methods

(==) :: Secret a -> Secret a -> Bool #

(/=) :: Secret a -> Secret a -> Bool #

Show (Secret a) Source #

N.B. This instance of Show is not law abiding.

This instance exists because we sometimes use Secret in data types that have to derive Show (due to other constraints on those data types).

This is not a pattern to follow; it's an exception.

Instance details

Defined in Log

Methods

showsPrec :: Int -> Secret a -> ShowS #

show :: Secret a -> String #

showList :: [Secret a] -> ShowS #

ToJSON (Secret a) Source # 
Instance details

Defined in Log

mkSecret :: a -> Secret a Source #

Wrap a value in a secret to prevent it from being accidentally logged.

Debug.log "Logging a secret" (mkSecret "My PIN is 1234") --> Logging a secret: Secret *****

unSecret :: Secret a -> a Source #

Retrieve the original value from a secret. Be very careful with this and ask yourself: is there really no way I can pass this value on as a secret further before I need to unwrap it?

The longer a value is wrapped in a Secret, the smaller the odds of it accidentally being logged.

For use in observability modules

data Context where Source #

Extra information to attach to a log message. It is passed a string key defining what the data is and a value with a ToJSON instance.

Constructors

Context :: ToJSON a => Text -> a -> Context 

data TriageInfo Source #

A logged message for log levels warning and above. Because these levels indicate a (potential) problem we want to provide some additional data that would help a triager figure out what next steps to take.

Constructors

TriageInfo 

Fields

Instances
Generic TriageInfo Source # 
Instance details

Defined in Log

Associated Types

type Rep TriageInfo :: Type -> Type #

ToJSON TriageInfo Source # 
Instance details

Defined in Log

type Rep TriageInfo Source # 
Instance details

Defined in Log

type Rep TriageInfo = D1 (MetaData "TriageInfo" "Log" "nri-prelude-0.1.0.0-2gUsYHgRMh6ZiXvL1ZtOs" False) (C1 (MetaCons "TriageInfo" PrefixI True) (S1 (MetaSel (Just "impact") NoSourceUnpackedness NoSourceStrictness DecidedStrict) (Rec0 Impact) :*: S1 (MetaSel (Just "advisory") NoSourceUnpackedness NoSourceStrictness DecidedStrict) (Rec0 Text)))

data Impact Source #

Classification of the levels of impact an issue might have on end-users.

Instances
Show Impact Source # 
Instance details

Defined in Log

ToJSON Impact Source # 
Instance details

Defined in Log