Log topic filtering (#312)
* comment * split out coders and add log level endpoin * adjust info url * add log filtering test * don't stringify cid * add log level test
This commit is contained in:
parent
ccf3d04dc8
commit
f36dc54eda
|
@ -34,81 +34,18 @@ import ../conf
|
|||
import ../contracts
|
||||
import ../streams
|
||||
|
||||
import ./coders
|
||||
import ./json
|
||||
|
||||
logScope:
|
||||
topics = "codex restapi"
|
||||
|
||||
proc validate(
|
||||
pattern: string,
|
||||
value: string): int
|
||||
{.gcsafe, raises: [Defect].} =
|
||||
0
|
||||
|
||||
proc encodeString(cid: type Cid): Result[string, cstring] =
|
||||
ok($cid)
|
||||
|
||||
proc decodeString(T: type Cid, value: string): Result[Cid, cstring] =
|
||||
Cid
|
||||
.init(value)
|
||||
.mapErr do(e: CidError) -> cstring:
|
||||
case e
|
||||
of CidError.Incorrect: "Incorrect Cid".cstring
|
||||
of CidError.Unsupported: "Unsupported Cid".cstring
|
||||
of CidError.Overrun: "Overrun Cid".cstring
|
||||
else: "Error parsing Cid".cstring
|
||||
|
||||
proc encodeString(peerId: PeerID): Result[string, cstring] =
|
||||
ok($peerId)
|
||||
|
||||
proc decodeString(T: type PeerID, value: string): Result[PeerID, cstring] =
|
||||
PeerID.init(value)
|
||||
|
||||
proc encodeString(address: MultiAddress): Result[string, cstring] =
|
||||
ok($address)
|
||||
|
||||
proc decodeString(T: type MultiAddress, value: string): Result[MultiAddress, cstring] =
|
||||
MultiAddress
|
||||
.init(value)
|
||||
.mapErr do(e: string) -> cstring: cstring(e)
|
||||
|
||||
proc decodeString(T: type SomeUnsignedInt, value: string): Result[T, cstring] =
|
||||
Base10.decode(T, value)
|
||||
|
||||
proc encodeString(value: SomeUnsignedInt): Result[string, cstring] =
|
||||
ok(Base10.toString(value))
|
||||
|
||||
proc decodeString(T: type Duration, value: string): Result[T, cstring] =
|
||||
let v = ? Base10.decode(uint32, value)
|
||||
ok(v.minutes)
|
||||
|
||||
proc encodeString(value: Duration): Result[string, cstring] =
|
||||
ok($value)
|
||||
|
||||
proc decodeString(T: type bool, value: string): Result[T, cstring] =
|
||||
try:
|
||||
ok(value.parseBool())
|
||||
except CatchableError as exc:
|
||||
let s: cstring = exc.msg
|
||||
err(s) # err(exc.msg) won't compile
|
||||
|
||||
proc encodeString(value: bool): Result[string, cstring] =
|
||||
ok($value)
|
||||
|
||||
proc decodeString(_: type UInt256, value: string): Result[UInt256, cstring] =
|
||||
try:
|
||||
ok UInt256.fromHex(value)
|
||||
except ValueError as e:
|
||||
err e.msg.cstring
|
||||
|
||||
proc decodeString(_: type array[32, byte],
|
||||
value: string): Result[array[32, byte], cstring] =
|
||||
try:
|
||||
ok array[32, byte].fromHex(value)
|
||||
except ValueError as e:
|
||||
err e.msg.cstring
|
||||
|
||||
proc decodeString[T: PurchaseId | RequestId | Nonce](_: type T,
|
||||
value: string): Result[T, cstring] =
|
||||
array[32, byte].decodeString(value).map(id => T(id))
|
||||
|
||||
proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter =
|
||||
var router = RestRouter.init(validate)
|
||||
router.api(
|
||||
|
@ -186,7 +123,7 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter =
|
|||
trace "Excepting streaming blocks", exc = exc.msg
|
||||
return RestApiResponse.error(Http500)
|
||||
finally:
|
||||
trace "Sent bytes", cid = $id.get(), bytes
|
||||
trace "Sent bytes", cid = id.get(), bytes
|
||||
if not stream.isNil:
|
||||
await stream.close()
|
||||
|
||||
|
@ -210,12 +147,14 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter =
|
|||
let nodes = params.nodes |? 1
|
||||
let tolerance = params.nodes |? 0
|
||||
|
||||
without purchaseId =? await node.requestStorage(cid,
|
||||
without purchaseId =? await node.requestStorage(
|
||||
cid,
|
||||
params.duration,
|
||||
nodes,
|
||||
tolerance,
|
||||
params.reward,
|
||||
params.expiry), error:
|
||||
|
||||
return RestApiResponse.error(Http500, error.msg)
|
||||
|
||||
return RestApiResponse.response(purchaseId.toHex)
|
||||
|
@ -259,9 +198,31 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter =
|
|||
# if we got here something went wrong?
|
||||
return RestApiResponse.error(Http500)
|
||||
|
||||
router.api(
|
||||
MethodPost,
|
||||
"/api/codex/v1/debug/chronicles/loglevel") do (
|
||||
level: Option[string]) -> RestApiResponse:
|
||||
## Set log level at run time
|
||||
##
|
||||
## e.g. `chronicles/loglevel?level=DEBUG`
|
||||
##
|
||||
## `level` - chronicles log level
|
||||
##
|
||||
|
||||
without res =? level and level =? res:
|
||||
return RestApiResponse.error(Http400, "Missing log level")
|
||||
|
||||
try:
|
||||
{.gcsafe.}:
|
||||
updateLogLevel(level)
|
||||
except CatchableError as exc:
|
||||
return RestApiResponse.error(Http500, exc.msg)
|
||||
|
||||
return RestApiResponse.response("")
|
||||
|
||||
router.api(
|
||||
MethodGet,
|
||||
"/api/codex/v1/info") do () -> RestApiResponse:
|
||||
"/api/codex/v1/debug/info") do () -> RestApiResponse:
|
||||
## Print rudimentary node information
|
||||
##
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
## Nim-Codex
|
||||
## Copyright (c) 2022 Status Research & Development GmbH
|
||||
## Licensed under either of
|
||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
## at your option.
|
||||
## This file may not be copied, modified, or distributed except according to
|
||||
## those terms.
|
||||
|
||||
import std/sugar
|
||||
|
||||
import pkg/presto
|
||||
import pkg/chronos
|
||||
import pkg/libp2p
|
||||
import pkg/stew/base10
|
||||
import pkg/stew/byteutils
|
||||
import pkg/stew/results
|
||||
import pkg/stint
|
||||
|
||||
import ../sales
|
||||
import ../purchasing
|
||||
|
||||
proc encodeString*(cid: type Cid): Result[string, cstring] =
|
||||
ok($cid)
|
||||
|
||||
proc decodeString*(T: type Cid, value: string): Result[Cid, cstring] =
|
||||
Cid
|
||||
.init(value)
|
||||
.mapErr do(e: CidError) -> cstring:
|
||||
case e
|
||||
of CidError.Incorrect: "Incorrect Cid".cstring
|
||||
of CidError.Unsupported: "Unsupported Cid".cstring
|
||||
of CidError.Overrun: "Overrun Cid".cstring
|
||||
else: "Error parsing Cid".cstring
|
||||
|
||||
proc encodeString*(peerId: PeerId): Result[string, cstring] =
|
||||
ok($peerId)
|
||||
|
||||
proc decodeString*(T: type PeerId, value: string): Result[PeerId, cstring] =
|
||||
PeerID.init(value)
|
||||
|
||||
proc encodeString*(address: MultiAddress): Result[string, cstring] =
|
||||
ok($address)
|
||||
|
||||
proc decodeString*(T: type MultiAddress, value: string): Result[MultiAddress, cstring] =
|
||||
MultiAddress
|
||||
.init(value)
|
||||
.mapErr do(e: string) -> cstring: cstring(e)
|
||||
|
||||
proc decodeString*(T: type SomeUnsignedInt, value: string): Result[T, cstring] =
|
||||
Base10.decode(T, value)
|
||||
|
||||
proc encodeString*(value: SomeUnsignedInt): Result[string, cstring] =
|
||||
ok(Base10.toString(value))
|
||||
|
||||
proc decodeString*(T: type Duration, value: string): Result[T, cstring] =
|
||||
let v = ? Base10.decode(uint32, value)
|
||||
ok(v.minutes)
|
||||
|
||||
proc encodeString*(value: Duration): Result[string, cstring] =
|
||||
ok($value)
|
||||
|
||||
proc decodeString*(T: type bool, value: string): Result[T, cstring] =
|
||||
try:
|
||||
ok(value.parseBool())
|
||||
except CatchableError as exc:
|
||||
let s: cstring = exc.msg
|
||||
err(s) # err(exc.msg) won't compile
|
||||
|
||||
proc encodeString*(value: bool): Result[string, cstring] =
|
||||
ok($value)
|
||||
|
||||
proc decodeString*(_: type UInt256, value: string): Result[UInt256, cstring] =
|
||||
try:
|
||||
ok UInt256.fromHex(value)
|
||||
except ValueError as e:
|
||||
err e.msg.cstring
|
||||
|
||||
proc decodeString*(_: type array[32, byte],
|
||||
value: string): Result[array[32, byte], cstring] =
|
||||
try:
|
||||
ok array[32, byte].fromHex(value)
|
||||
except ValueError as e:
|
||||
err e.msg.cstring
|
||||
|
||||
proc decodeString*[T: PurchaseId | RequestId | Nonce](_: type T,
|
||||
value: string): Result[T, cstring] =
|
||||
array[32, byte].decodeString(value).map(id => T(id))
|
||||
|
||||
proc decodeString*(t: typedesc[string],
|
||||
value: string): Result[string, cstring] =
|
||||
ok(value)
|
||||
|
||||
proc encodeString*(value: string): RestResult[string] =
|
||||
ok(value)
|
|
@ -39,13 +39,18 @@ ethersuite "Integration tests":
|
|||
"--eth-account=" & $accounts[0]
|
||||
], debug = false)
|
||||
|
||||
let
|
||||
bootstrap = strip(
|
||||
$(parseJson(client.get(baseurl1 & "/debug/info").body)["spr"]),
|
||||
chars = {'"'})
|
||||
|
||||
node2 = startNode([
|
||||
"--api-port=8081",
|
||||
"--data-dir=" & dataDir2,
|
||||
"--nat=127.0.0.1",
|
||||
"--disc-ip=127.0.0.1",
|
||||
"--disc-port=8091",
|
||||
"--bootstrap-node=" & strip($(parseJson(client.get(baseurl1 & "/info").body)["spr"]), chars = {'"'}),
|
||||
"--bootstrap-node=" & bootstrap,
|
||||
"--persistence",
|
||||
"--eth-account=" & $accounts[1]
|
||||
], debug = false)
|
||||
|
@ -59,10 +64,15 @@ ethersuite "Integration tests":
|
|||
dataDir2.removeDir()
|
||||
|
||||
test "nodes can print their peer information":
|
||||
let info1 = client.get(baseurl1 & "/info").body
|
||||
let info2 = client.get(baseurl2 & "/info").body
|
||||
let info1 = client.get(baseurl1 & "/debug/info").body
|
||||
let info2 = client.get(baseurl2 & "/debug/info").body
|
||||
check info1 != info2
|
||||
|
||||
test "nodes should set chronicles log level":
|
||||
client.headers = newHttpHeaders({ "Content-Type": "text/plain" })
|
||||
let filter = "/debug/chronicles/loglevel?level=DEBUG;TRACE:codex"
|
||||
check client.request(baseurl1 & filter, httpMethod = HttpPost, body = "").status == "200 OK"
|
||||
|
||||
test "node accepts file uploads":
|
||||
let url = baseurl1 & "/upload"
|
||||
let response = client.post(url, "some file contents")
|
||||
|
|
Loading…
Reference in New Issue