In a Hyperledger Fabric Smart Contract how do I turn on logging?

558 views Asked by At

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.

2

There are 2 answers

0
Calanais On

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

  • CRITICAL, ERROR maps to Level.SEVERE
  • WARNING maps to Level.WARNING
  • INFO maps to Level.INFO
  • NOTICE maps to Level.CONFIG
  • DEBUG maps to Level.FINEST

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

  • CRITICIAL maps to fatal
  • ERROR maps to to error
  • WARNING maps to to warn
  • DEBUG maps to to debug
  • INFO maps to to info

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.

  1. You may wish to map your own logging level changes here for your own Smart Contract code.
  2. For the other transaction functions you're likely to want to implement some validation of who is submitting the logging change. You might even want to update a specific key in the ledger to record the change.

Where do the logs go?

They go to the stdout of the chaincode process, which will usually be captured by the environment, eg Kubernetes.

0
myeongkil kim On

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