Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impl Logger AddContext summand #162

Merged
merged 40 commits into from
Jan 6, 2020
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
97cf2aa
add katip-es deps
IvantheTricourne Dec 17, 2019
cc47cd5
wip es scribe/logger
IvantheTricourne Dec 18, 2019
0c9ad23
Merge branch 'master' of github.com:f-o-a-m/hs-abci into es-scribe-lo…
IvantheTricourne Dec 18, 2019
82741df
add metrics instructions
IvantheTricourne Dec 18, 2019
42c2e7f
toggle response/request logs to ES or console
IvantheTricourne Dec 18, 2019
fa171e6
add some comments and rename app logger middleware for clarity
IvantheTricourne Dec 18, 2019
598680d
some code cleanup
IvantheTricourne Dec 19, 2019
b5ba744
wip
martyall Dec 19, 2019
1140afb
wip almost builds
IvantheTricourne Dec 19, 2019
b29682e
builds
IvantheTricourne Dec 19, 2019
1623d9b
config verbosity levels
IvantheTricourne Dec 19, 2019
1ba4a35
add addContext summand
IvantheTricourne Dec 19, 2019
7297235
stylish
IvantheTricourne Dec 19, 2019
2d4cfaa
use addContext in nameservice
IvantheTricourne Dec 19, 2019
572d067
add datadog logs and elk installation instructions
IvantheTricourne Dec 20, 2019
70cd67a
es
IvantheTricourne Dec 20, 2019
e0f139a
add contextevent type to add event type field for logs
IvantheTricourne Dec 20, 2019
107659a
use local namespace in res/req middleware
IvantheTricourne Dec 20, 2019
5f3f232
test image
IvantheTricourne Dec 20, 2019
9cb37c7
update readme
IvantheTricourne Dec 20, 2019
c0c28e6
adjust vertical screenshots
IvantheTricourne Dec 20, 2019
32187a1
use different images
IvantheTricourne Dec 20, 2019
2de83c4
change image links to master branch
IvantheTricourne Dec 20, 2019
8d12125
add image for creating a filter in kibana discovery
IvantheTricourne Dec 20, 2019
154f349
use third person
IvantheTricourne Dec 20, 2019
e65dbf5
Merge branch 'master' of github.com:f-o-a-m/hs-abci into context-summand
IvantheTricourne Dec 23, 2019
69a2d3d
add default select method
IvantheTricourne Dec 23, 2019
69aefae
rm unused imports
IvantheTricourne Dec 23, 2019
93d9cd7
use ContextEvent in token and nameservice modules
IvantheTricourne Dec 23, 2019
ec0add4
move context event to events
IvantheTricourne Dec 24, 2019
efd3757
Merge branch 'master' of github.com:f-o-a-m/hs-abci into context-summand
IvantheTricourne Dec 24, 2019
94c9dff
Add logEvent and emitAndLogEvent
IvantheTricourne Dec 24, 2019
a1ae399
Switch logEvent to info
IvantheTricourne Dec 24, 2019
2900ca3
Remove event_type logItem from resp/req loggers
IvantheTricourne Jan 2, 2020
6a12cba
remove emitAndLogEvent
IvantheTricourne Jan 3, 2020
130390f
Merge branch 'master' into context-summand
IvantheTricourne Jan 3, 2020
896b581
stylish
IvantheTricourne Jan 3, 2020
20cf9f0
Merge branch 'master' into context-summand
IvantheTricourne Jan 3, 2020
87bfcf1
stylish
IvantheTricourne Jan 3, 2020
1024c1c
Add TxEff constraint to token router
IvantheTricourne Jan 3, 2020
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
130 changes: 127 additions & 3 deletions hs-abci-examples/nameservice/README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,147 @@
# nameservice

## Metrics
## Metrics via Prometheus
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before commenting on any of this, is there any way to have kibana pull metrics from prometheus in the same way datadog does. This would be good to fix some confusing asymmetry between server metrics and application metrics, and would also be easier to explain that you can now use either Kibana or datadog to view anything you want, or both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I’ll investigate.

Copy link
Contributor Author

@IvantheTricourne IvantheTricourne Dec 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blinky3713

It seems MetricBeat is an option from the ELK folks that can scrape prometheus exporters and servers. Given we're already using ELK stack, this seems to be a pretty good option.

Similar to the datadog agent, it also has a docker-compose.


Run `nameservice` via the `Makefile`:

```
make deploy-nameservice-local
```

Along with running `nameservice`, this also starts a Prometheus] metrics server.
Along with running `nameservice`, this command also starts a Prometheus metrics server.
By default, the metrics server runs on `localhost:9200`. To use a different port,
set the `STATS_PORT` environment variable to the desired port value.

To see these metrics in Datadog, follow the
[Prometheus host config instructions](https://docs.datadoghq.com/getting_started/integrations/prometheus/?tab=host#pagetitle)
to configure a local Datadog agent to scrape the endpoint.
to configure a local Datadog agent to scrape the endpoint. At minimum, to scrape all
`nameservice` prometheus metrics, the appropriate `conf.yaml` (described above) should
contain the following settings:

```yaml
init_config:

instances:

- prometheus_url: http://localhost:9200/metrics
## namespace option prefixes all metric names in datadog
namespace: prometheus
## metrics names used in the nameservice app
metrics:
- count_buy
- count_set
- count_delete
- histogram_buy*
- histogram_set*
- histogram_delete*
```

Alternatively, use the `docker-compose` command:

```
make deploy-nameservice-docker
```

Once the `nameservice` server is running, start a Tendermint node:

```bash
> tendermint init
> tendermint node
```

Then run the `nameservice` tests:

```bash
make test-nameservice
```

Once the test run is completed, you should now be able to view metrics
on [Datadog's metrics explorer](https://app.datadoghq.com/metric/explorer).
Firstly, ensure that the prometheus server is populated with metrics by
visiting `localhost:9200/metrics` in a browser. It should look something like this:

```
# TYPE count_buy counter
count_buy 4
# TYPE count_delete counter
count_delete 1
# TYPE count_set counter
count_set 2
# TYPE histogram_buy histogram
histogram_buy_bucket{le="1.0e-4"} 0.0
...
# TYPE histogram_delete histogram
histogram_delete_bucket{le="1.0e-4"} 0.0
...
# TYPE histogram_set histogram
histogram_set_bucket{le="1.0e-4"} 0.0
...
```

Now, in Datadog's metrics explorer, we can search for metrics
prefixed with the `namespace` value (i.e., `prometheus`) set above:

<img src="https://raw.githubusercontent.com/f-o-a-m/hs-abci/master/hs-abci-examples/nameservice/images/prometheus-metrics.png" width="50%"/>

## Alternative Logging

In addition to Prometheus metrics, the `nameservice` app includes options for
logging to Elasticsearch (ES) and Datadog metrics logging. By default, the app
logs everything to the console:

```
[2019-12-20 16:19:27][nameservice.server][Info][local][PID 89617][ThreadId 21][type:info] Request Received
[2019-12-20 16:19:27][nameservice.server][Info][local][PID 89617][ThreadId 21][message_type:info][response_time:2.6e-5][message_count:1]
```

These logs include request/response info and some event and metric logging.

Alternatively, the app is set up to log the same information to ES
and Datadog by setting the following environment variables:

```bash
DD_API_KEY ## Datadog API key
ES_HOST ## Elasticsearch server host
ES_PORT ## Elasticsearch server port
```

We recommend using the [ELK (v683) docker image](https://hub.docker.com/r/sebp/elk/tags)
to run an ES server alongside a Kibana instance to search and filter incoming logs.

```bash
> docker pull sebp/elk:683
> docker run -p 5601:5601 -p 9201:9200 -p 5044:5044 -it --name elk sebp/elk:683
```

**NOTE:** This command remaps the `ES_PORT` value from `9200` to `9201` to avoid collision with
the Prometheus server that `nameservice` runs by default. The Kibana instance runs on port `5601`.

After both Kibana and ES are running, start `nameservice` and a Tendermint node
via the commands:

```bash
> DD_API_KEY=<DD_API_KEY> ES_HOST=localhost ES_PORT=9201 make deploy-nameservice
> tendermint init
> tendermint node
```

At this point, there should be no logs printed on the console. If a valid
Datadog API Key is provided, metrics logs are available on
[Datadog's log explorer](https://app.datadoghq.com/logs).

<img src="https://raw.githubusercontent.com/f-o-a-m/hs-abci/master/hs-abci-examples/nameservice/images/logs-tab.png" width="25%"/>

To view ES logs on Kibana, go to `Management` on the sidebar and create a Kibana index pattern for `nameservice`:

<img src="https://raw.githubusercontent.com/f-o-a-m/hs-abci/master/hs-abci-examples/nameservice/images/kibana-management.png" width="25%"/>

<img src="https://raw.githubusercontent.com/f-o-a-m/hs-abci/master/hs-abci-examples/nameservice/images/create-index.png" width="75%"/>

Finally, under `Discover`, we can add filters to view specific logs:

<img src="https://raw.githubusercontent.com/f-o-a-m/hs-abci/master/hs-abci-examples/nameservice/images/kibana-discover.png" width="25%"/>

For example, after running `nameservice` tests, we can add a filter to see
event logs for `NameClaimed`, `NameRemapped` and `NameDeleted`:

<img src="https://raw.githubusercontent.com/f-o-a-m/hs-abci/master/hs-abci-examples/nameservice/images/create-filter.png" width="75%"/>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added hs-abci-examples/nameservice/images/logs-tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import qualified Tendermint.SDK.BaseApp as BaseApp
import Tendermint.SDK.Crypto (Secp256k1)
import qualified Tendermint.SDK.Modules.Auth as A


type EffR =
N.NameserviceEffs :&
T.TokenEffs :&
Expand Down
2 changes: 1 addition & 1 deletion hs-abci-examples/nameservice/src/Nameservice/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ makeAppConfig = do
ddApiKey <- cs <$> MaybeT (lookupEnv "DD_API_KEY")
pure $ P.MetricsScrapingConfig prometheusPort ddApiKey
metricsMap <- newMVar empty
c <- BaseApp.makeContext (KL.InitialLogNamespace "dev" "simple-storage") prometheusEnv
c <- BaseApp.makeContext (KL.InitialLogNamespace "dev" "nameservice") prometheusEnv
prometheusServer <- newIORef Nothing
addScribesToLogEnv $
AppConfig { _baseAppContext = c
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Nameservice.Modules.Nameservice.Messages
import Nameservice.Modules.Nameservice.Types
import Nameservice.Modules.Token (Token, TokenEffs,
burn, mint, transfer)
import Polysemy (Member, Members, Sem,
import Polysemy (Members, Sem,
interpret, makeSem)
import Polysemy.Error (Error, mapError,
throw)
Expand All @@ -26,7 +26,7 @@ makeSem ''NameserviceKeeper
type NameserviceEffs = '[NameserviceKeeper, Error NameserviceError]

storeKey :: BaseApp.StoreKey NameserviceModuleName
storeKey = BaseApp.StoreKey . cs . symbolVal $ Proxy @ NameserviceModuleName
storeKey = BaseApp.StoreKey . cs . symbolVal $ Proxy @NameserviceModuleName

eval
:: Members [BaseApp.RawStore, Error BaseApp.AppError] r
Expand All @@ -50,7 +50,7 @@ eval = mapError BaseApp.makeAppError . evalNameservice
--------------------------------------------------------------------------------

setName
:: Member (Output BaseApp.Event) r
:: Members [BaseApp.Logger, Output BaseApp.Event] r
=> Members NameserviceEffs r
=> SetName
-> Sem r ()
Expand All @@ -63,14 +63,16 @@ setName SetName{..} = do
then throw $ UnauthorizedSet "Setter must be the owner of the Name."
else do
putWhois setNameName currentWhois {whoisValue = setNameValue}
BaseApp.emit NameRemapped
{ nameRemappedName = setNameName
, nameRemappedNewValue = setNameValue
, nameRemappedOldValue = whoisValue
}
let event = NameRemapped
{ nameRemappedName = setNameName
, nameRemappedNewValue = setNameValue
, nameRemappedOldValue = whoisValue
}
BaseApp.emit event
BaseApp.logEvent event

deleteName
:: Members [Token, Output BaseApp.Event] r
:: Members [BaseApp.Logger, Token, Output BaseApp.Event] r
=> Members NameserviceEffs r
=> DeleteName
-> Sem r ()
Expand All @@ -84,13 +86,14 @@ deleteName DeleteName{..} = do
else do
mint deleteNameOwner whoisPrice
deleteWhois deleteNameName
BaseApp.emit NameDeleted
{ nameDeletedName = deleteNameName
}

let event = NameDeleted
{ nameDeletedName = deleteNameName
}
BaseApp.emit event
BaseApp.logEvent event

buyName
:: Member (Output BaseApp.Event) r
:: Members [BaseApp.Logger, Output BaseApp.Event] r
=> Members TokenEffs r
=> Members NameserviceEffs r
=> BuyName
Expand All @@ -108,7 +111,7 @@ buyName msg = do
Just whois -> buyClaimedName msg whois
where
buyUnclaimedName
:: Member (Output BaseApp.Event) r
:: Members [BaseApp.Logger, Output BaseApp.Event] r
=> Members TokenEffs r
=> Members NameserviceEffs r
=> BuyName
Expand All @@ -121,17 +124,19 @@ buyName msg = do
, whoisPrice = buyNameBid
}
putWhois buyNameName whois
BaseApp.emit NameClaimed
{ nameClaimedOwner = buyNameBuyer
, nameClaimedName = buyNameName
, nameClaimedValue = buyNameValue
, nameClaimedBid = buyNameBid
}
let event = NameClaimed
{ nameClaimedOwner = buyNameBuyer
, nameClaimedName = buyNameName
, nameClaimedValue = buyNameValue
, nameClaimedBid = buyNameBid
}
BaseApp.emit event
BaseApp.logEvent event

buyClaimedName
:: Members NameserviceEffs r
=> Members TokenEffs r
=> Member (Output BaseApp.Event) r
=> Members [BaseApp.Logger, Output BaseApp.Event] r
=> BuyName
-> Whois
-> Sem r ()
Expand All @@ -145,11 +150,13 @@ buyName msg = do
, whoisPrice = buyNameBid
, whoisValue = buyNameValue
}
BaseApp.emit NameClaimed
{ nameClaimedOwner = buyNameBuyer
, nameClaimedName = buyNameName
, nameClaimedValue = buyNameValue
, nameClaimedBid = buyNameBid
}
let event = NameClaimed
{ nameClaimedOwner = buyNameBuyer
, nameClaimedName = buyNameName
, nameClaimedValue = buyNameValue
, nameClaimedBid = buyNameBid
}
BaseApp.emit event
BaseApp.logEvent event
else throw (InsufficientBid "Bid must exceed the price.")

Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ instance FromJSON NameClaimed where
parseJSON = A.genericParseJSON nameClaimedAesonOptions
instance BaseApp.ToEvent NameClaimed where
makeEventType _ = "NameClaimed"
instance BaseApp.Select NameClaimed
instance Event.FromEvent NameClaimed

data NameRemapped = NameRemapped
Expand All @@ -124,6 +125,7 @@ instance FromJSON NameRemapped where
parseJSON = A.genericParseJSON nameRemappedAesonOptions
instance BaseApp.ToEvent NameRemapped where
makeEventType _ = "NameRemapped"
instance BaseApp.Select NameRemapped
instance Event.FromEvent NameRemapped

data NameDeleted = NameDeleted
Expand All @@ -139,4 +141,6 @@ instance FromJSON NameDeleted where
parseJSON = A.genericParseJSON nameDeletedAesonOptions
instance BaseApp.ToEvent NameDeleted where
makeEventType _ = "NameDeleted"
instance BaseApp.Select NameDeleted
instance Event.FromEvent NameDeleted

Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,18 @@ eval = mapError BaseApp.makeAppError . evalToken
--------------------------------------------------------------------------------

faucetAccount
:: Members [Error TokenError, Output BaseApp.Event, Token] r
:: Members [BaseApp.Logger, Output BaseApp.Event] r
=> Members TokenEffs r
=> FaucetAccount
-> Sem r ()
faucetAccount FaucetAccount{..} = do
mint faucetAccountTo faucetAccountAmount
BaseApp.emit Faucetted
{ faucettedAccount = faucetAccountTo
, faucettedAmount = faucetAccountAmount
}
let event = Faucetted
{ faucettedAccount = faucetAccountTo
, faucettedAmount = faucetAccountAmount
}
BaseApp.emit event
BaseApp.logEvent event

getBalance
:: Member Token r
Expand All @@ -63,7 +66,8 @@ getBalance address =
fromMaybe (Amount 0) <$> getBalance' address

transfer
:: Members [Error TokenError, Output BaseApp.Event, Token] r
:: Members [BaseApp.Logger, Output BaseApp.Event] r
=> Members TokenEffs r
=> Address
-> Amount
-> Address
Expand All @@ -79,15 +83,17 @@ transfer addr1 amount addr2 = do
-- update both balances
putBalance addr1 newBalance1
putBalance addr2 newBalance2
BaseApp.emit $ TransferEvent
{ transferEventAmount = amount
, transferEventTo = addr2
, transferEventFrom = addr1
}
let event = TransferEvent
{ transferEventAmount = amount
, transferEventTo = addr2
, transferEventFrom = addr1
}
BaseApp.emit event
BaseApp.logEvent event
else throw (InsufficientFunds "Insufficient funds for transfer.")

burn
:: Members [Error TokenError, Token] r
:: Members TokenEffs r
=> Address
-> Amount
-> Sem r ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import Nameservice.Modules.Token.Keeper (TokenEffs, burn,
import Nameservice.Modules.Token.Messages (Burn (..),
TokenMessage (..),
Transfer (..))
import Polysemy (Member, Members, Sem)
import Polysemy.Output (Output)
import Tendermint.SDK.BaseApp (Event)
import Polysemy (Members, Sem)
import Tendermint.SDK.BaseApp (BaseAppEffs)
import Tendermint.SDK.Types.Message (Msg (..))
import Tendermint.SDK.Types.Transaction (RoutedTx (..), Tx (..))

router
:: Members TokenEffs r
=> Member (Output Event) r
=> Members BaseAppEffs r
=> RoutedTx TokenMessage
-> Sem r ()
router (RoutedTx Tx{txMsg}) =
Expand Down
Loading