problem: unnecessary exceptions in logs when an unavailable blockchain is requested
This commit is contained in:
17
src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt
Normal file
17
src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package io.emeraldpay.dshackle
|
||||||
|
|
||||||
|
import io.emeraldpay.grpc.Chain
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that should be handled/logged without a stacktrace in production
|
||||||
|
*/
|
||||||
|
open class SilentException(message: String) : Exception(message) {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blockchain is not available or not supported by current instance of the Dshackle
|
||||||
|
*/
|
||||||
|
class UnsupportedBlockchain(val blockchainId: Int): SilentException("Unsupported blockchain $blockchainId") {
|
||||||
|
constructor(chain: Chain) : this(chain.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.rpc
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||||
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.upstream.*
|
import io.emeraldpay.dshackle.upstream.*
|
||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
import io.emeraldpay.dshackle.quorum.CallQuorum
|
import io.emeraldpay.dshackle.quorum.CallQuorum
|
||||||
@@ -81,10 +82,10 @@ class NativeCall(
|
|||||||
fun prepareCall(request: BlockchainOuterClass.NativeCallRequest): Flux<CallContext<RawCallDetails>> {
|
fun prepareCall(request: BlockchainOuterClass.NativeCallRequest): Flux<CallContext<RawCallDetails>> {
|
||||||
val chain = Chain.byId(request.chain.number)
|
val chain = Chain.byId(request.chain.number)
|
||||||
if (chain == Chain.UNSPECIFIED) {
|
if (chain == Chain.UNSPECIFIED) {
|
||||||
return Flux.error(CallFailure(0, Exception("Invalid chain id: ${request.chain.number}")))
|
return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(request.chain.number)))
|
||||||
}
|
}
|
||||||
val upstream = upstreams.getUpstream(chain)
|
val upstream = upstreams.getUpstream(chain)
|
||||||
?: return Flux.error(CallFailure(0, Exception("Chain ${chain.id} is unavailable")))
|
?: return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(chain)))
|
||||||
|
|
||||||
return prepareCall(request, upstream)
|
return prepareCall(request, upstream)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.rpc
|
|||||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.Defaults
|
import io.emeraldpay.dshackle.Defaults
|
||||||
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.upstream.Selector
|
import io.emeraldpay.dshackle.upstream.Selector
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
@@ -34,7 +35,6 @@ import reactor.core.publisher.Mono
|
|||||||
import reactor.core.publisher.TopicProcessor
|
import reactor.core.publisher.TopicProcessor
|
||||||
import reactor.core.publisher.toFlux
|
import reactor.core.publisher.toFlux
|
||||||
import reactor.core.scheduler.Scheduler
|
import reactor.core.scheduler.Scheduler
|
||||||
import java.lang.Exception
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -95,10 +95,10 @@ class TrackAddress(
|
|||||||
private fun initializeSimple(request: BlockchainOuterClass.BalanceRequest): Flux<SimpleAddress> {
|
private fun initializeSimple(request: BlockchainOuterClass.BalanceRequest): Flux<SimpleAddress> {
|
||||||
val chain = Chain.byId(request.asset.chainValue)
|
val chain = Chain.byId(request.asset.chainValue)
|
||||||
if (!upstreams.isAvailable(chain)) {
|
if (!upstreams.isAvailable(chain)) {
|
||||||
return Flux.error(Exception("Unsupported chain ${request.asset.chainValue}"))
|
return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
||||||
}
|
}
|
||||||
if (request.asset.code?.toLowerCase() != "ether") {
|
if (request.asset.code?.toLowerCase() != "ether") {
|
||||||
return Flux.error(Exception("Unsupported asset ${request.asset.code}"))
|
return Flux.error(SilentException("Unsupported asset ${request.asset.code}"))
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
request.address.addrTypeCase == Common.AnyAddress.AddrTypeCase.ADDRESS_SINGLE ->
|
request.address.addrTypeCase == Common.AnyAddress.AddrTypeCase.ADDRESS_SINGLE ->
|
||||||
@@ -133,8 +133,16 @@ class TrackAddress(
|
|||||||
buildResponse(it)
|
buildResponse(it)
|
||||||
}
|
}
|
||||||
Flux.merge(current, bus).doFinally { stopTracking(tracked) }
|
Flux.merge(current, bus).doFinally { stopTracking(tracked) }
|
||||||
}.doOnError { t ->
|
}
|
||||||
log.warn("Failed to process subscription", t)
|
.doOnError { t ->
|
||||||
|
if (t is SilentException) {
|
||||||
|
if (t is SilentException.UnsupportedBlockchain) {
|
||||||
|
log.warn("Unsupported blockchain: ${t.blockchainId}")
|
||||||
|
}
|
||||||
|
log.debug("Failed to process subscription", t)
|
||||||
|
} else {
|
||||||
|
log.warn("Failed to process subscription", t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +175,7 @@ class TrackAddress(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getBalance(addr: SimpleAddress): Mono<Wei> {
|
fun getBalance(addr: SimpleAddress): Mono<Wei> {
|
||||||
val up = upstreams.getUpstream(addr.chain) ?: return Mono.error(Exception("Unsupported chain: ${addr.chain}"))
|
val up = upstreams.getUpstream(addr.chain) ?: return Mono.error(SilentException.UnsupportedBlockchain(addr.chain))
|
||||||
return up.getApi(Selector.empty)
|
return up.getApi(Selector.empty)
|
||||||
.flatMap { api -> api.executeAndConvert(Commands.eth().getBalance(addr.address, BlockTag.LATEST)) }
|
.flatMap { api -> api.executeAndConvert(Commands.eth().getBalance(addr.address, BlockTag.LATEST)) }
|
||||||
.timeout(Defaults.timeout)
|
.timeout(Defaults.timeout)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.rpc
|
|||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.upstream.Selector
|
import io.emeraldpay.dshackle.upstream.Selector
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||||
@@ -142,7 +143,7 @@ class TrackTx(
|
|||||||
fun prepareTracking(request: BlockchainOuterClass.TxStatusRequest): TxDetails {
|
fun prepareTracking(request: BlockchainOuterClass.TxStatusRequest): TxDetails {
|
||||||
val chain = Chain.byId(request.chainValue)
|
val chain = Chain.byId(request.chainValue)
|
||||||
if (!clients.containsKey(chain)) {
|
if (!clients.containsKey(chain)) {
|
||||||
throw Exception("Unsupported blockchain: ${chain}")
|
throw SilentException.UnsupportedBlockchain(chain)
|
||||||
}
|
}
|
||||||
val bus = TopicProcessor.create<Notification>()
|
val bus = TopicProcessor.create<Notification>()
|
||||||
val details = TxDetails(
|
val details = TxDetails(
|
||||||
@@ -208,7 +209,7 @@ class TrackTx(
|
|||||||
|
|
||||||
private fun loadWeight(tx: TxDetails): Mono<TxDetails> {
|
private fun loadWeight(tx: TxDetails): Mono<TxDetails> {
|
||||||
val upstream = upstreams.getUpstream(tx.chain)
|
val upstream = upstreams.getUpstream(tx.chain)
|
||||||
?: return Mono.error(Exception("Unsupported blockchain: ${tx.chain}"))
|
?: return Mono.error(SilentException.UnsupportedBlockchain(tx.chain))
|
||||||
return upstream.getApi(Selector.empty)
|
return upstream.getApi(Selector.empty)
|
||||||
.flatMap { api -> api.executeAndConvert(Commands.eth().getBlock(tx.status.blockHash)) }
|
.flatMap { api -> api.executeAndConvert(Commands.eth().getBlock(tx.status.blockHash)) }
|
||||||
.map { block ->
|
.map { block ->
|
||||||
@@ -249,7 +250,7 @@ class TrackTx(
|
|||||||
|
|
||||||
private fun checkForUpdate(tx: TxDetails): Mono<TxDetails> {
|
private fun checkForUpdate(tx: TxDetails): Mono<TxDetails> {
|
||||||
val initialStatus = tx.status
|
val initialStatus = tx.status
|
||||||
val upstream = upstreams.getUpstream(tx.chain) ?: return Mono.error(Exception("Unsupported blockchain: ${tx.chain}"))
|
val upstream = upstreams.getUpstream(tx.chain) ?: return Mono.error(SilentException.UnsupportedBlockchain(tx.chain))
|
||||||
val execution = upstream.getApi(Selector.empty)
|
val execution = upstream.getApi(Selector.empty)
|
||||||
.flatMap { api -> api.executeAndConvert(Commands.eth().getTransaction(tx.txid)) }
|
.flatMap { api -> api.executeAndConvert(Commands.eth().getTransaction(tx.txid)) }
|
||||||
return execution
|
return execution
|
||||||
|
|||||||
Reference in New Issue
Block a user