Reputation: 1600
I've written a Hyperledger Fabric Smart Contracts in Java and NodeJS. How do I turn on different levels of logging?
The Fabric Smart Contract classes themselves log at the INFO level, how do I change that when the contract is deployed and running?
EDIT: Included Node.js (for JavaScript and Typescript) as well as Java.
Upvotes: 1
Views: 597
Reputation: 2586
When developing chaincode, dev-mode is recommended. You can check this from the link below.
hyperledger/fabric/peer-devmode
At this time, you can easily modify the log level by changing the CORE_CHAINCODE_LOGLEVEL
option when starting chaincode.
cd examples/chaincode/go/chaincode_example02
go build
CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_ADDRESS=127.0.0.1:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./chaincode_example02
Upvotes: 1
Reputation: 1600
The solution to this is to implement a simple 'helper' transaction. As an example, you could create another class as follows.
In Java:
@Contract(name = "ContractSupport")
public class ContractSupport implements ContractInterface {
/**
* Required Default Constructor.
*/
public ContractSupport() {
}
/**
* Sets the log level.
*
* The setLogLevel method has the required parsing to manage the levels.
*
* @param ctx Transactional Context
* @param level string id
*/
@Transaction(intent = TYPE.EVALUATE)
public void setLogLevel(final Context ctx, final String level) {
Logging.setLogLevel(level);
}
}
Note that this has the @Contract()
annotation so it's callable from the Client SDKs as any other transaction function. Remember to make sure the name in the annotation is different from your other contracts, and don't use the @Default()
annotation - that should be used by your own code.
The strings that are accepted by the Logging.setLogLevel
method and how they map to java.util.logging
levels are
Anything else is mapped to INFO.
All the loggers that start org.hyperledger
will be updated.
In Node.js (this example is in Typescript)
@Info({ title: 'ContractSupport', description: 'Utilties to support the contract' })
export class ContractSupport extends Contract {
@Transaction(false)
public async setLogLevel(ctx: Context, loglevel: string): Promise<void> {
const logger = ctx.logger.setLevel(loglevel);
}
}
This is using the @Info
annotation to specify the contract title and the super class of Contract
is used. Remember to add this contract class to the list of exports in the index.js/index.ts otherwise it won't be picked up.
The mapping here maps to the levels used by Winston
INFO is the default if something else is supplied.
Do I submit or evaluate? In the example, I've marked this as evaluate. Remember this annotation is a recommendation, it is ultimately how the client application submits the transaction that determines if it sent for ordering.
As this is not affecting the ledger, but the actually running chaincode you can use either evaluate or submit. The important thing is to think about which chaincode instances will run the code.
Evaluate will send to one peer and therefore one chaincode will enable logging. Submit will send to potentially other peers in other organizations. Do you want to enable additional logging across all of those?
It's probably best to use evaluate, and then return the level to INFO when you've got the diagnostics you need.
Why do I have to code this myself? Valid question, there are 2 reasons.
Where do the logs go?
They go to the stdout of the chaincode process, which will usually be captured by the environment, eg Kubernetes.
Upvotes: 1