Skip to content

Commit 0af2767

Browse files
committed
Merge branch 'master' into refactor-for-otel
2 parents 1b53164 + 4a7ee59 commit 0af2767

112 files changed

Lines changed: 2836 additions & 1292 deletions

File tree

Some content is hidden

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

.github/workflows/test-with-ff.js.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,10 @@ jobs:
184184
- name: Copy cypress.config_cicd.ts to cypress.config.ts to listen to correct port
185185
working-directory: ladybug/ladybug-ff-cypress-test
186186
run: cp cypress.config_cicd.ts cypress.config.ts
187-
- name: Use Node.js 20.x
187+
- name: Use Node.js 24.x
188188
uses: actions/setup-node@v4
189189
with:
190-
node-version: 20.x
190+
node-version: 24.x
191191
cache: "yarn"
192192
cache-dependency-path: "**/yarn.lock"
193193
- name: Update yarn

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ wip
2020
skip-replace-inject.txt
2121
.flattened-pom.xml
2222
FrankConfig.xsd
23+
CLAUDE_CONTEXT.md

ladybug-common/src/main/java/org/wearefrank/ladybug/Config.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2022-2025 WeAreFrank!
2+
Copyright 2022-2026 WeAreFrank!
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -234,6 +234,16 @@ List<String> metadataNames() {
234234
metadataNames.add("numberOfCheckpoints");
235235
metadataNames.add("estimatedMemoryUsage");
236236
metadataNames.add("storageSize");
237+
// Metadata name "host" is known but it should not be shown by default.
238+
// Class TestTool fills it with the IP address by which the device running
239+
// Ladybug is accessed. Instrumented applications can also assign a different
240+
// value to metadata item "host".
241+
//
242+
// Metadata name "application" is special because it is decided
243+
// dynamically whether it is shown in the table of the debug tab in
244+
// the Angular UI. See class View for the logic that will omit
245+
// "application" as metadata name from a view when not relevant.
246+
metadataNames.add("application");
237247
return metadataNames;
238248
}
239249

@@ -257,6 +267,8 @@ ReportXmlTransformer reportXmlTransformer() {
257267
@DefaultBean
258268
@Bean
259269
@Scope("singleton")
270+
// ladybug-test-webapp and the Frank!Framework have their own implementation
271+
// that supersede this default.
260272
String xsltResource() {
261273
return "ladybug/default.xslt";
262274
}

ladybug-common/src/main/java/org/wearefrank/ladybug/MetadataExtractor.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2020, 2022-2025 WeAreFrank!, 2018-2019 Nationale-Nederlanden
2+
Copyright 2020, 2022-2026 WeAreFrank!, 2018-2019 Nationale-Nederlanden
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -112,6 +112,12 @@ public String getLabel(String metadataName) {
112112
if (metadataName.equals("duration")) {
113113
return "Duration";
114114
}
115+
if (metadataName.equals("host")) {
116+
return "Host";
117+
}
118+
if (metadataName.equals("application")) {
119+
return "Application";
120+
}
115121
for (MetadataFieldExtractor metadataFieldExtractor : metadataFieldExtractors) {
116122
if (metadataFieldExtractor.getName().equals(metadataName)) {
117123
label = metadataFieldExtractor.getLabel();
@@ -167,6 +173,12 @@ public String getShortLabel(String metadataName) {
167173
if (metadataName.equals("duration")) {
168174
return "Duration";
169175
}
176+
if (metadataName.equals("host")) {
177+
return "Host";
178+
}
179+
if (metadataName.equals("application")) {
180+
return "Application";
181+
}
170182
for (MetadataFieldExtractor metadataFieldExtractor : metadataFieldExtractors) {
171183
if (metadataFieldExtractor.getName().equals(metadataName)) {
172184
shortLabel = metadataFieldExtractor.getShortLabel();
@@ -225,6 +237,12 @@ private Object getMetadataAsObject(Report report, String metadataName) {
225237
if (metadataName.equals("duration")) {
226238
return Long.valueOf(report.getEndTime() - report.getStartTime());
227239
}
240+
if (metadataName.equals("host")) {
241+
return report.getHost();
242+
}
243+
if (metadataName.equals("application")) {
244+
return report.getApplication();
245+
}
228246
if (metadataName.equals("variables")) {
229247
return report.getVariables();
230248
}

ladybug-common/src/main/java/org/wearefrank/ladybug/Report.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ public class Report implements Serializable {
8383
private List<Checkpoint> checkpoints = new ArrayList<Checkpoint>();
8484
private @Setter @Getter String transformation;
8585
private Map<String, String> variables;
86-
private @Setter @Getter boolean rerunnable = true;
86+
87+
private @Getter @Setter String host;
88+
private @Getter @Setter String application;
89+
8790
// Please note that the get and set methods need @Transient annotation for XmlEncoder to not store the property.
8891
// This is in contrast to serialization / ObjectOutputStream that is using variables (and doesn't look at get and
8992
// set methods) and needs a variable to be declared transient to not store the field.
@@ -903,6 +906,8 @@ public Report clone() throws CloneNotSupportedException {
903906
variables.putAll(getVariables());
904907
report.setVariables(variables);
905908
}
909+
report.setHost(host);
910+
report.setApplication(application);
906911
List<Checkpoint> checkpoints = new ArrayList<Checkpoint>();
907912
for (Checkpoint checkpoint : this.checkpoints) {
908913
checkpoint = checkpoint.clone();
@@ -936,6 +941,12 @@ public String toXml(ReportRunner reportRunner) {
936941
builder.append(" EndTime=\"" + endTime + "\"");
937942
builder.append(" NumberOfCheckpoints=\"" + getNumberOfCheckpoints() + "\"");
938943
builder.append(" EstimatedMemoryUsage=\"" + getEstimatedMemoryUsage() + "\"");
944+
if (getHost() != null) {
945+
builder.append(" Host=\"" + getHost() + "\"");
946+
}
947+
if (getApplication() != null) {
948+
builder.append(" Application=\"" + getApplication() + "\"");
949+
}
939950
builder.append(">");
940951
for (Checkpoint checkpoint : checkpoints) {
941952
String message;

ladybug-common/src/main/java/org/wearefrank/ladybug/TestTool.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package org.wearefrank.ladybug;
1717

1818
import java.lang.invoke.MethodHandles;
19+
import java.net.InetAddress;
20+
import java.net.UnknownHostException;
1921
import java.rmi.server.UID;
2022
import java.util.ArrayList;
2123
import java.util.HashMap;
@@ -106,15 +108,37 @@ public class TestTool {
106108
private @Setter String openTelemetryEndpoint;
107109
private Tracer tracer;
108110

111+
private @Getter @Setter String host = null;
112+
private @Getter @Setter String application = null;
113+
109114
private AtomicInteger inProgressStorageNameSeq = new AtomicInteger(0);
110115

116+
public TestTool() {
117+
initializeHostAstIpAddress();
118+
}
119+
111120
@PostConstruct
112121
public void init() {
122+
for (View view: views) {
123+
view.setTestTool(this);
124+
}
113125
if (openTelemetryEndpoint != null) {
114126
tracer = OpenTelemetryUtil.getOpenTelemetryTracer(openTelemetryEndpoint);
115127
}
116128
}
117129

130+
private void initializeHostAstIpAddress() {
131+
try {
132+
InetAddress localMachine = InetAddress.getLocalHost();
133+
String ipAddress = localMachine.getHostAddress();
134+
// It would be nice to log this IP address, but that requires quite a big change of
135+
// the test code. The test code would have to ignore the log statement.
136+
this.host = ipAddress;
137+
} catch(UnknownHostException uhe) {
138+
log.error("Cannot initialize host because of UnknownHostException", uhe);
139+
}
140+
}
141+
118142
public void reset() {
119143
regexFilter = defaultRegexFilter;
120144
reportGeneratorEnabled = defaultReportGeneratorEnabled;
@@ -414,6 +438,8 @@ private Report createReport(String correlationId, String name, int checkpointTyp
414438
if (checkpointType == CheckpointType.STARTPOINT.toInt()) {
415439
log.debug("Create new report for '" + correlationId + "'");
416440
report = new Report();
441+
report.setHost(host);
442+
report.setApplication(application);
417443
report.setStartTime(System.currentTimeMillis());
418444
report.setTestTool(this);
419445
report.setCorrelationId(correlationId);
@@ -1282,4 +1308,4 @@ public static String getSpecificationVersion() {
12821308
public static String getImplementationVersion() {
12831309
return Package.getPackage("org.wearefrank.ladybug").getImplementationVersion();
12841310
}
1285-
}
1311+
}

ladybug-common/src/main/java/org/wearefrank/ladybug/filter/View.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
package org.wearefrank.ladybug.filter;
1717

1818
import java.util.ArrayList;
19+
import java.util.HashSet;
1920
import java.util.List;
2021
import java.util.Map;
22+
import java.util.Set;
23+
import java.util.stream.Collectors;
2124

2225
import org.springframework.beans.factory.annotation.Autowired;
2326

@@ -29,6 +32,7 @@
2932
import org.wearefrank.ladybug.Checkpoint;
3033
import org.wearefrank.ladybug.MetadataExtractor;
3134
import org.wearefrank.ladybug.Report;
35+
import org.wearefrank.ladybug.TestTool;
3236
import org.wearefrank.ladybug.echo2.BeanParent;
3337
import org.wearefrank.ladybug.echo2.Echo2Application;
3438
import org.wearefrank.ladybug.echo2.reports.ReportsComponent;
@@ -42,7 +46,10 @@ public class View implements BeanParent {
4246
protected String name;
4347
protected String nodeLinkStrategy;
4448
private @Setter @Getter @Inject @Autowired Storage debugStorage;
45-
private @Setter @Getter @Inject @Resource(name="metadataNames") List<String> metadataNames;
49+
private @Setter @Inject @Resource(name="metadataNames") List<String> metadataNames;
50+
// No autowired annotation here, otherwise we would have a circular dependency.
51+
// This member variable is instantiated by class TestTool.
52+
private @Setter TestTool testTool;
4653
private Map<String, String> metadataFilter;
4754
private List<CheckpointMatcher> checkpointMatchers;
4855
private BeanParent beanParent;
@@ -74,6 +81,20 @@ public String getNodeLinkStrategy() {
7481
return nodeLinkStrategy;
7582
}
7683

84+
// Metadata name "application" is special because it is determined dynamically whether it is returned
85+
// by a View. When a database storage is used and when the database stores reports from different
86+
// applications, showing column "application" in the metadata table of the debug tab makes sense.
87+
// If the storage only holds reports of a single application, then metadata name "application"
88+
// should be omitted. We want that these two situations do not require different Spring configurations
89+
// for Ladybug. This is the reason we have this method to filter the metadata names.
90+
public List<String> getMetadataNames() {
91+
Set<String> omit = new HashSet<>();
92+
if(testTool.getApplication() == null) {
93+
omit.add("application");
94+
}
95+
return metadataNames.stream().filter(n -> !omit.contains(n)).collect(Collectors.toList());
96+
}
97+
7798
public void setMetadataFilter(Map<String, String> metadataFilter) {
7899
this.metadataFilter = metadataFilter;
79100
}

ladybug-common/src/main/java/org/wearefrank/ladybug/storage/database/DatabaseStorage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ public long getMaxStorageDays() {
177177

178178
@PostConstruct
179179
public void init() throws StorageException {
180+
log.debug("DatabaseStorage uses metadata names {}", metadataNames);
180181
if (!(getMetadataNames() != null && getMetadataNames().contains(getStorageIdColumn()))) {
181182
throw new StorageException("List metadataNames " + metadataNames
182183
+ " should at least contain storageId column name '" + getStorageIdColumn() + "'");

ladybug-common/src/main/java/org/wearefrank/ladybug/storage/proofofmigration/ProofOfMigrationErrorsView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2022, 2024, 2025 WeAreFrank!
2+
Copyright 2022, 2024, 2025, 2026 WeAreFrank!
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.

ladybug-common/src/main/java/org/wearefrank/ladybug/storage/proofofmigration/ProofOfMigrationStorage.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2022-2025 WeAreFrank!
2+
Copyright 2022-2026 WeAreFrank!
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -216,6 +216,8 @@ public Report getReport(Integer storageId) throws StorageException {
216216
return list;
217217
});
218218
Report report = new Report();
219+
// Host and application are not set. This is not a report originating from
220+
// a Java application that is tested with Ladybug.
219221
report.setTestTool(testTool);
220222
report.setStorage(this);
221223
report.setStorageId(storageId);

0 commit comments

Comments
 (0)