Skip to content

Commit 814e870

Browse files
authored
Merge pull request #44 from corda/logging-cordapp
2 parents fc94563 + 7835df8 commit 814e870

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1145
-28
lines changed

Basic/README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
This folder features basic sample projects, each of them demonstrates low level cordapp functionalities, such as [RPC connection](https://docs.corda.net/docs/corda-os/api-rpc.html#api-rpc-operations), messaging, etc.
44

55
### [Cordapp Example](./cordapp-example):
6-
A simple exploratory sample for the official [Corda online training](https://training.corda.net).
6+
A simple exploratory sample for the official [Corda online training](https://training.corda.net).
77

88
### [Database Access](./flow-database-access):
9-
This CorDapp provides a simple example of how the node database can be accessed within flows. In this case, the flows maintain a table of cryptocurrency values in the node's database.
9+
This CorDapp provides a simple example of how the node database can be accessed within flows. In this case, the flows maintain a table of cryptocurrency values in the node's database.
1010

1111
### [Http Access](./flow-http-access):
12-
This CorDapp provides a simple example of how HTTP requests can be made in flows. In this case, the flow makes an HTTP request to retrieve the original BitCoin readme from GitHub.
12+
This CorDapp provides a simple example of how HTTP requests can be made in flows. In this case, the flow makes an HTTP request to retrieve the original BitCoin readme from GitHub.
1313

1414
### [Ping Pong](./ping-pong):
15-
This CorDapp allows a node to ping any other node on the network, demonstrating stateless communication between nodes.
16-
15+
This CorDapp allows a node to ping any other node on the network, demonstrating stateless communication between nodes.
1716

1817

Features/README.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,49 @@
33
This folder features several sample projects, each of them demonstrates different specific features of corda.
44

55
### [Blacklist -- Attachment](./attachment-blacklist):
6-
This CorDapp allows nodes to reach agreement over arbitrary strings of text, but only with parties that are not included in the blacklist uploaded to the nodes as an [attachment](https://training.corda.net/corda-details/attachments/).
6+
This CorDapp allows nodes to reach agreement over arbitrary strings of text, but only with parties that are not included in the blacklist uploaded to the nodes as an [attachment](https://training.corda.net/corda-details/attachments/).
77

88
### [Sendfile -- Attachment](./attachment-sendfile):
9-
This Cordapp shows how to upload and download an [attachment](https://training.corda.net/corda-details/attachments/) via a flow.
9+
This Cordapp shows how to upload and download an [attachment](https://training.corda.net/corda-details/attachments/) via a flow.
1010
<p align="center">
1111
<img src="./attachment-sendfile/graph.png" alt="Corda" width="700">
1212
</p>
1313

1414
### [Whistleblower -- Confidential Identity ](./confidentialidentity-whistleblower):
15-
This CorDapp is a simple showcase of [confidential identities](https://docs.corda.net/docs/corda-os/api-identity.html#confidential-identities) (i.e. anonymous public keys).
15+
This CorDapp is a simple showcase of [confidential identities](https://docs.corda.net/docs/corda-os/api-identity.html#confidential-identities) (i.e. anonymous public keys).
1616

1717
### [Autopayroll -- CordaService](./cordaservice-autopayroll):
18-
This Cordapp shows how to trigger a flow with vault update(completion of prior flows) using [CordaService](https://training.corda.net/corda-details/automation/#services) & [trackby](https://training.corda.net/corda-details/automation-solution/#track-and-notify).
18+
This Cordapp shows how to trigger a flow with vault update(completion of prior flows) using [CordaService](https://training.corda.net/corda-details/automation/#services) & [trackby](https://training.corda.net/corda-details/automation-solution/#track-and-notify).
1919
<p align="center">
2020
<img src="./cordaservice-autopayroll/webpic/Business%20Logic.png" alt="Corda" width="500">
2121
</p>
2222

2323
### [Trade Reporting -- ObservableStates](./observablestates-tradereporting):
24-
This CorDapp shows how Corda's [observable states](https://docs.corda.net/docs/corda-os/4.4/tutorial-observer-nodes.html#observer-nodes) feature works. Observable states is the ability for nodes who are not participants in a transaction to still store them if the transactions are sent to them.
24+
This CorDapp shows how Corda's [observable states](https://docs.corda.net/docs/corda-os/4.4/tutorial-observer-nodes.html#observer-nodes) feature works. Observable states is the ability for nodes who are not participants in a transaction to still store them if the transactions are sent to them.
2525

2626
### [Prime Number -- Oracle](./oracle-primenumber):
2727
This CorDapp implements an [oracle service](https://training.corda.net/corda-details/oracles) that allows nodes to:
2828

2929
* Request the Nth prime number
30-
* Request the oracle's signature to prove that the number included in their transaction is actually the Nth prime number
30+
* Request the oracle's signature to prove that the number included in their transaction is actually the Nth prime number
3131

3232

3333
### [Car Insurance -- QueryableState](./queryablestate-carinsurance):
34-
This CorDapp demonstrates [QueryableState](https://docs.corda.net/docs/corda-os/api-persistence.html) works in Corda. Corda allows developers to have the ability to expose some or all parts of their states to a custom database table using an ORM tools. To support this feature the state must implement `QueryableState`.
34+
This CorDapp demonstrates [QueryableState](https://docs.corda.net/docs/corda-os/api-persistence.html) works in Corda. Corda allows developers to have the ability to expose some or all parts of their states to a custom database table using an ORM tools. To support this feature the state must implement `QueryableState`.
3535

3636
### [Sanctionsbody -- ReferenceStates](./referencestates-sanctionsbody):
3737
This CorDapp demonstrates the use of [reference states](https://training.corda.net/corda-details/reference-states/) in a transaction and in the verification method of a contract.
3838

39-
This CorDapp allows two nodes to enter into an IOU agreement, but enforces that both parties belong to a list of sanctioned entities. This list of sanctioned entities is taken from a referenced SanctionedEntities state.
39+
This CorDapp allows two nodes to enter into an IOU agreement, but enforces that both parties belong to a list of sanctioned entities. This list of sanctioned entities is taken from a referenced SanctionedEntities state.
4040

4141
### [Heartbeat -- SchedulableState](./schedulablestate-heartbeat):
42-
This CorDapp is a simple showcase of [scheduled activities](https://docs.corda.net/docs/corda-os/event-scheduling.html#how-to-implement-scheduled-events) (i.e. activities started by a node at a specific time without direct input from the node owner).
42+
This CorDapp is a simple showcase of [scheduled activities](https://docs.corda.net/docs/corda-os/event-scheduling.html#how-to-implement-scheduled-events) (i.e. activities started by a node at a specific time without direct input from the node owner).
43+
4344
<p align="center">
4445
<img src="./schedulablestate-heartbeat/heart.jpg" alt="Corda" width="500">
4546
</p>
47+
48+
49+
### [CustomLogging -- YoCordapp](./customlogging-yocordapp):
50+
This cordapp has some examples on how to setup custom logging with corda for either json logging and other tooling.
51+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2016, R3 Limited.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Logging CorDapp
2+
3+
## Custom Logging
4+
5+
This is a modified version of the original yo cordapp with some additions to use custom log4j2 configurations.
6+
7+
8+
The primary example we've implemented here is json logging which is configured in `config/dev/log4j2.xml`.
9+
10+
This gives us the ability to use Log4j thread contexts to log arbitrary objects or data points in json format.
11+
12+
In this example not only do the node logs output in json but we can add arbitrary key value pairs as well.
13+
14+
```java
15+
// here we have our first opportunity to log out the contents of the flow arguments.
16+
ThreadContext.put("initiator", me.getName().toString());
17+
ThreadContext.put("target", target.getName().toString());
18+
// publish to the log with the additional context
19+
logger.info("Initializing the transaction.");
20+
```
21+
22+
When we log this message, it gets output along with the other key value pairs we've specified in a JSON format:
23+
```
24+
{
25+
"instant": {
26+
"epochSecond": 1612982209,
27+
"nanoOfSecond": 487000000
28+
},
29+
"thread": "Node thread-1",
30+
"level": "INFO",
31+
"loggerName": "net.corda",
32+
"message": "Initializing the transaction.",
33+
"endOfBatch": true,
34+
"loggerFqcn": "org.apache.logging.slf4j.Log4jLogger",
35+
"contextMap": {
36+
"actor_id": "internalShell",
37+
"actor_owning_identity": "O=PartyA, L=London, C=GB",
38+
"actor_store_id": "NODE_CONFIG",
39+
"fiber-id": "10000001",
40+
"flow-id": "94543b19-b949-441e-9962-bc50dcd7ad55",
41+
"initiator": "O=PartyA, L=London, C=GB",
42+
"invocation_id": "a53a3a5d-b450-456e-a0f1-dfb7dcdce6dd",
43+
"invocation_timestamp": "2021-02-10T18:36:49.312Z",
44+
"origin": "internalShell",
45+
"session_id": "e8ba737e-e809-4a14-8c3b-284b7ae5ed88",
46+
"session_timestamp": "2021-02-10T18:36:49.022Z",
47+
"target": "O=PartyB, L=New York, C=US",
48+
"thread-id": "168"
49+
},
50+
"threadId": 168,
51+
"threadPriority": 5
52+
}
53+
```
54+
This can be quite powerful if you're looking to produce a consumable output stream to a log aggregator like splunk.
55+
56+
You can end up getting log feeds in json that look something like this:
57+
58+
```json
59+
{"instant":{"epochSecond":1612369055,"nanoOfSecond":12000000},"thread":"main","level":"INFO","loggerName":"net.corda.node.internal.Node","message":"Vendor: Corda Open Source","endOfBatch":true,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":1,"threadPriority":5}
60+
. . .More Node Startup loggings
61+
62+
// when our flow is run we see the log we specified
63+
{"instant":{"epochSecond":1612460471,"nanoOfSecond":866000000},"thread":"pool-10-thread-2","level":"INFO","loggerName":"net.corda.tools.shell.FlowShellCommand","message":"Executing command \"flow start net.corda.samples.logging.flows.YoFlow target: PartyA\",","endOfBatch":true,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":224,"threadPriority":5}
64+
{"instant":{"epochSecond":1612460472,"nanoOfSecond":304000000},"thread":"Node thread-1","level":"INFO","loggerName":"net.corda","message":"Initializing the transaction.","endOfBatch":true,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":166,"threadPriority":5}
65+
{"instant":{"epochSecond":1612460472,"nanoOfSecond":428000000},"thread":"pool-10-thread-2","level":"WARN","loggerName":"net.corda.tools.shell.utlities.StdoutANSIProgressRenderer","message":"Cannot find console appender - progre
66+
```
67+
68+
## Usage
69+
70+
71+
### Pre-Requisites
72+
73+
See https://docs.corda.net/getting-set-up.html.
74+
75+
76+
### Running the CorDapp
77+
78+
Open a terminal and go to the project root directory and type: (to deploy the nodes using bootstrapper)
79+
```
80+
./gradlew clean deployNodes
81+
```
82+
Then type: (to run the nodes)
83+
84+
```
85+
./build/nodes/runnodes
86+
```
87+
88+
When the nodes run you'll be able to see the node's json log files in their respesctive `logs` folders.
89+
This logging configuration will add a new file that you can view.
90+
91+
```shell
92+
tail -f build/nodes/PartyA/logs/node.json
93+
94+
{"instant":{"epochSecond":1612543764,"nanoOfSecond":930000000},"thread":"main","level":"INFO","loggerName":"net.corda.cliutils.CliWrapperBase","message":"Application Args: run-migration-scripts --core-schemas --app-schemas","endOfBatch":true,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","contextMap":{},"threadId":1,"threadPriority":5}
95+
{"instant":{"epochSecond":1612543766,"nanoOfSecond":300000000}
96+
97+
. . .
98+
99+
```
100+
101+
### Sending a Yo
102+
103+
We will interact with the nodes via their specific shells. When the nodes are up and running, use the following command to send a
104+
Yo to another node:
105+
106+
```
107+
flow start YoFlow target: PartyB
108+
```
109+
110+
Where `NODE_NAME` is 'PartyA' or 'PartyB'. The space after the `:` is required. You are not required to use the full
111+
X500 name in the node shell. Note you can't sent a Yo! to yourself because that's not cool!
112+
113+
To see all the Yo's! other nodes have sent you in your vault (you do not store the Yo's! you send yourself), run:
114+
115+
```
116+
run vaultQuery contractStateType: YoState
117+
```
118+
119+
### Other ways to use this log configuration
120+
121+
The above method will run all nodes together but if you're running your corda node manually all you need to do is specify the particular config file.
122+
123+
You can do that by just running the jar directly:
124+
125+
```shell
126+
java -Dlog4j.configurationFile=logging-cordapp/build/resources/main/log4j2.xml -jar corda.jar
127+
```
128+
129+
> notice that all we're doing is adding this param to the command we'd otherwise use to run corda in order to specify the log file.
130+
131+
132+
## Attribution
133+
134+
This example was built with help from [Splunk](https://splunk.com), and they have our thanks.
135+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Corda and the Corda logo are trademarks of R3CEV LLC and its affiliates. All rights reserved.
2+
3+
For R3CEV LLC's trademark and logo usage information, please consult our Trademark Usage Policy at
4+
https://www.r3.com/trademark-policy/.
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
buildscript {
2+
Properties constants = new Properties()
3+
file("$projectDir/../constants.properties").withInputStream { constants.load(it) }
4+
5+
ext {
6+
corda_release_group = constants.getProperty("cordaReleaseGroup")
7+
corda_release_version = constants.getProperty("cordaVersion")
8+
corda_gradle_plugins_version = constants.getProperty("gradlePluginsVersion")
9+
junit_version = constants.getProperty("junitVersion")
10+
quasar_version = constants.getProperty("quasarVersion")
11+
log4j_version = constants.getProperty("log4jVersion")
12+
slf4j_version = constants.getProperty("slf4jVersion")
13+
corda_platform_version = constants.getProperty("platformVersion").toInteger()
14+
}
15+
16+
repositories {
17+
mavenLocal()
18+
mavenCentral()
19+
jcenter()
20+
maven { url 'https://software.r3.com/artifactory/corda-releases' }
21+
}
22+
23+
dependencies {
24+
classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version"
25+
classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"
26+
classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version"
27+
}
28+
}
29+
30+
allprojects {
31+
apply from: "${rootProject.projectDir}/repositories.gradle"
32+
apply plugin: 'java'
33+
34+
repositories {
35+
mavenLocal()
36+
jcenter()
37+
mavenCentral()
38+
maven { url 'https://software.r3.com/artifactory/corda' }
39+
maven { url 'https://jitpack.io' }
40+
}
41+
42+
tasks.withType(JavaCompile) {
43+
options.compilerArgs << "-parameters" // Required for shell commands.
44+
}
45+
46+
jar {
47+
// CorDapps do not configure a Node's logging.
48+
exclude '**/log4j2*.xml'
49+
}
50+
}
51+
52+
apply plugin: 'net.corda.plugins.cordapp'
53+
apply plugin: 'net.corda.plugins.cordformation'
54+
apply plugin: 'net.corda.plugins.quasar-utils'
55+
56+
sourceSets {
57+
main {
58+
resources {
59+
srcDir rootProject.file("config/dev")
60+
}
61+
}
62+
}
63+
64+
dependencies {
65+
// Corda dependencies.
66+
cordaCompile "$corda_release_group:corda-core:$corda_release_version"
67+
cordaCompile "$corda_release_group:corda-node-api:$corda_release_version"
68+
cordaRuntime "$corda_release_group:corda:$corda_release_version"
69+
70+
// CorDapp dependencies.
71+
cordapp project(":workflows")
72+
cordapp project(":contracts")
73+
74+
// specific dependency for log4j2 core
75+
cordaCompile "org.apache.logging.log4j:log4j-core:${log4j_version}"
76+
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
77+
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
78+
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
79+
}
80+
81+
cordapp {
82+
info {
83+
name "Logging CorDapp"
84+
vendor "Corda Open Source"
85+
targetPlatformVersion corda_platform_version
86+
minimumPlatformVersion corda_platform_version
87+
}
88+
}
89+
90+
task deployNodesJava(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
91+
92+
nodeDefaults {
93+
projectCordapp {
94+
deploy = false
95+
}
96+
97+
cordapp project(':contracts')
98+
cordapp project(':workflows')
99+
100+
runSchemaMigration = false
101+
102+
// there are other ways to specify that config for example
103+
extraConfig = [
104+
custom: [
105+
jvmArgs: ["-Dlog4j.configurationFile="+projectDir+"/config/dev/log4j2.xml"]
106+
]
107+
]
108+
109+
}
110+
111+
node {
112+
name "O=Notary,L=London,C=GB"
113+
notary = [validating : false]
114+
p2pPort 10002
115+
rpcSettings {
116+
address("localhost:10003")
117+
adminAddress("localhost:10043")
118+
}
119+
}
120+
node {
121+
name "O=PartyA,L=London,C=GB"
122+
p2pPort 10005
123+
rpcSettings {
124+
address("localhost:10006")
125+
adminAddress("localhost:10046")
126+
}
127+
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
128+
}
129+
node {
130+
name "O=PartyB,L=New York,C=US"
131+
p2pPort 10008
132+
rpcSettings {
133+
address("localhost:10009")
134+
adminAddress("localhost:10049")
135+
}
136+
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
137+
}
138+
139+
}
140+
141+

0 commit comments

Comments
 (0)