Skip to content

Commit 9ccff4d

Browse files
Merge branch 'main' into Add-otel-log-support-to-the-product-catalog-service
2 parents c8a33d5 + e18bb82 commit 9ccff4d

File tree

8 files changed

+237
-7
lines changed

8 files changed

+237
-7
lines changed

.github/workflows/label-pr.yml

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright The OpenTelemetry Authors
2+
# SPDX-License-Identifier: Apache-2.0
3+
# adds a label to a pull request if certain files are changed
4+
name: Label Pull Requests
5+
6+
on:
7+
pull_request:
8+
types: [opened, synchronize, reopened]
9+
10+
jobs:
11+
label:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v2
16+
17+
- name: Check for changed files
18+
id: file_changes
19+
uses: dorny/paths-filter@v2
20+
with:
21+
list-files: shell
22+
filters: |
23+
docsUpdateRequired:
24+
- 'src/flagd/**'
25+
helmUpdateRequired:
26+
- '.env'
27+
- 'docker-compose*.yml'
28+
- 'src/flagd/**'
29+
- 'src/grafana/**'
30+
- 'src/otelcollector/**'
31+
- 'src/prometheus/**'
32+
33+
- name: "Add Label: docs-update-required"
34+
if: steps.file_changes.outputs.docsUpdateRequired == 'true'
35+
uses: actions/github-script@v7
36+
with:
37+
github-token: ${{secrets.GITHUB_TOKEN}}
38+
script: |
39+
const issue_number = context.issue.number;
40+
github.issues.addLabels({
41+
issue_number: issue_number,
42+
owner: context.repo.owner,
43+
repo: context.repo.repo,
44+
labels: ['docs-update-required']
45+
})
46+
47+
- name: "Add Label: helm-update-required"
48+
if: steps.file_changes.outputs.helmUpdateRequired == 'true'
49+
uses: actions/github-script@v7
50+
with:
51+
github-token: ${{secrets.GITHUB_TOKEN}}
52+
script: |
53+
const issue_number = context.issue.number;
54+
github.issues.addLabels({
55+
issue_number: issue_number,
56+
owner: context.repo.owner,
57+
repo: context.repo.repo,
58+
labels: ['helm-update-required']
59+
})

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ the release.
4141
([#1448](https://github.com/open-telemetry/opentelemetry-demo/pull/1448))
4242
* [cartservice] update .NET to .NET 8.0.3
4343
([#1460](https://github.com/open-telemetry/opentelemetry-demo/pull/1460))
44+
* [adservice] add adServiceManualGC feature flag
45+
([#1463](https://github.com/open-telemetry/opentelemetry-demo/pull/1463))
4446
* [frontendproxy] remove deprecated start_child_span option
4547
([#1469](https://github.com/open-telemetry/opentelemetry-demo/pull/1469))
4648
* [currency] fix metric name

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,21 +79,21 @@ Monday at 8:30 AM PST and anyone is welcome.
7979
([@open-telemetry/demo-maintainers](https://github.com/orgs/open-telemetry/teams/demo-maintainers)):
8080

8181
- [Austin Parker](https://github.com/austinlparker), Honeycomb
82-
- [Carter Socha](https://github.com/cartersocha), Lightstep
8382
- [Juliano Costa](https://github.com/julianocosta89), Datadog
83+
- [Mikko Viitanen](https://github.com/mviitane), Dynatrace
8484
- [Pierre Tessier](https://github.com/puckpuck), Honeycomb
8585

8686
[Approvers](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
8787
([@open-telemetry/demo-approvers](https://github.com/orgs/open-telemetry/teams/demo-approvers)):
8888

8989
- [Cedric Ziel](https://github.com/cedricziel) Grafana Labs
90-
- [Mikko Viitanen](https://github.com/mviitane), Dynatrace
9190
- [Penghan Wang](https://github.com/wph95), AppDynamics
9291
- [Reiley Yang](https://github.com/reyang), Microsoft
9392
- [Ziqi Zhao](https://github.com/fatsheep9146), Alibaba
9493

9594
Emeritus:
9695

96+
- [Carter Socha](https://github.com/cartersocha)
9797
- [Michael Maxwell](https://github.com/mic-max)
9898
- [Morgan McLean](https://github.com/mtwo)
9999

ide-gen-proto.sh

-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ gen_proto_dotnet cartservice
7171
gen_proto_go checkoutservice
7272
# gen_proto_cpp currencyservice
7373
# gen_proto_ruby emailservice
74-
gen_proto_elixir featureflagservice
7574
gen_proto_ts frontend
7675
gen_proto_js paymentservice
7776
gen_proto_go productcatalogservice

src/adservice/src/main/java/oteldemo/AdService.java

+20-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import oteldemo.Demo.Ad;
3535
import oteldemo.Demo.AdRequest;
3636
import oteldemo.Demo.AdResponse;
37+
import oteldemo.problempattern.GarbageCollectionTrigger;
3738
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
3839
import dev.openfeature.contrib.providers.flagd.FlagdProvider;
3940
import dev.openfeature.sdk.Client;
@@ -127,6 +128,9 @@ private enum AdResponseType {
127128

128129
private static class AdServiceImpl extends oteldemo.AdServiceGrpc.AdServiceImplBase {
129130

131+
private static final String ADSERVICE_FAILURE = "adServiceFailure";
132+
private static final String ADSERVICE_MANUAL_GC_FEATURE_FLAG = "adServiceManualGc";
133+
130134
private AdServiceImpl() {}
131135

132136
/**
@@ -177,8 +181,14 @@ public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
177181
Attributes.of(
178182
adRequestTypeKey, adRequestType.name(), adResponseTypeKey, adResponseType.name()));
179183

180-
if (checkAdFailure()) {
181-
throw new StatusRuntimeException(Status.RESOURCE_EXHAUSTED);
184+
if (getFeatureFlagEnabled(ADSERVICE_FAILURE)) {
185+
throw new StatusRuntimeException(Status.UNAVAILABLE);
186+
}
187+
188+
if (getFeatureFlagEnabled(ADSERVICE_MANUAL_GC_FEATURE_FLAG)) {
189+
logger.warn("Feature Flag " + ADSERVICE_MANUAL_GC_FEATURE_FLAG + " enabled, performing a manual gc now");
190+
GarbageCollectionTrigger gct = new GarbageCollectionTrigger();
191+
gct.doExecute();
182192
}
183193

184194
AdResponse reply = AdResponse.newBuilder().addAllAds(allAds).build();
@@ -193,12 +203,18 @@ public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
193203
}
194204
}
195205

196-
boolean checkAdFailure() {
206+
/**
207+
* Retrieves the status of a feature flag from the Feature Flag service.
208+
*
209+
* @param ff The name of the feature flag to retrieve.
210+
* @return {@code true} if the feature flag is enabled, {@code false} otherwise or in case of errors.
211+
*/
212+
boolean getFeatureFlagEnabled(String ff) {
197213
Client client = OpenFeatureAPI.getInstance().getClient();
198214
// TODO: Plumb the actual session ID from the frontend via baggage?
199215
UUID uuid = UUID.randomUUID();
200216
client.setEvaluationContext(new MutableContext().add("session", uuid.toString()));
201-
Boolean boolValue = client.getBooleanValue("adServiceFailure", false);
217+
Boolean boolValue = client.getBooleanValue(ff, false);
202218
return boolValue;
203219
}
204220
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package oteldemo.problempattern;
7+
8+
import java.lang.management.ManagementFactory;
9+
import java.util.concurrent.TimeUnit;
10+
11+
import org.apache.logging.log4j.LogManager;
12+
import org.apache.logging.log4j.Logger;
13+
14+
/**
15+
* The GarbageCollectionTrigger class is responsible for triggering manual garbage collection
16+
* at specified intervals to simulate memory pressure and measure the impact on performance.
17+
*/
18+
public class GarbageCollectionTrigger {
19+
private static final Logger logger = LogManager.getLogger(GarbageCollectionTrigger.class.getName());
20+
21+
private final long gc_delay;
22+
private final int finalize_delay;
23+
private final int maxObjects;
24+
25+
private long lastGC = 0;
26+
27+
private final MemoryUtils memUtils;
28+
29+
/**
30+
* Constructs a new GarbageCollectionTrigger with default values.
31+
*/
32+
public GarbageCollectionTrigger() {
33+
memUtils = new MemoryUtils(ManagementFactory.getMemoryMXBean());
34+
gc_delay = TimeUnit.SECONDS.toMillis(10);
35+
finalize_delay = 500;
36+
maxObjects = 500000;
37+
}
38+
39+
/**
40+
* Triggers manual garbage collection at specified intervals and measures the impact on performance.
41+
* It creates Entry objects to fill up memory and initiates garbage collection.
42+
*/
43+
public void doExecute() {
44+
if (System.currentTimeMillis() - lastGC > gc_delay) {
45+
logger.info("Triggering a manual garbage collection, next one in " + (gc_delay/1000) + " seconds.");
46+
// clear old data, we want to clear old Entry objects, because their finalization is expensive
47+
System.gc();
48+
49+
long total = 0;
50+
for (int i = 0; i < 10; i++) {
51+
while (memUtils.getHeapUsage() < 0.9 && memUtils.getObjectPendingFinalizationCount() < maxObjects) {
52+
new Entry();
53+
}
54+
long start = System.currentTimeMillis();
55+
System.gc();
56+
total += System.currentTimeMillis() - start;
57+
}
58+
logger.info("The artificially triggered GCs took: " + total + " ms");
59+
lastGC = System.currentTimeMillis();
60+
}
61+
62+
}
63+
64+
/**
65+
* The Entry class represents objects created for the purpose of triggering garbage collection.
66+
*/
67+
private class Entry {
68+
/**
69+
* Overrides the finalize method to introduce a delay, simulating finalization during garbage collection.
70+
*
71+
* @throws Throwable If an exception occurs during finalization.
72+
*/
73+
@SuppressWarnings("removal")
74+
@Override
75+
protected void finalize() throws Throwable {
76+
TimeUnit.MILLISECONDS.sleep(finalize_delay);
77+
super.finalize();
78+
}
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package oteldemo.problempattern;
7+
8+
import java.lang.management.MemoryMXBean;
9+
import java.lang.management.MemoryUsage;
10+
import org.apache.logging.log4j.LogManager;
11+
import org.apache.logging.log4j.Logger;
12+
13+
14+
/**
15+
* This class provides JVM heap related utility methods.
16+
*/
17+
public class MemoryUtils {
18+
19+
private static final Logger logger = LogManager.getLogger(MemoryUtils.class.getName());
20+
21+
private static final long NO_HEAP_LIMIT = -1;
22+
23+
private final MemoryMXBean memoryBean;
24+
25+
/**
26+
* @param memoryBean defines which {@link MemoryMXBean} is to use
27+
*/
28+
public MemoryUtils(MemoryMXBean memoryBean) {
29+
this.memoryBean = memoryBean;
30+
}
31+
32+
33+
/**
34+
* @return The current heap usage as a decimal number between 0.0 and 1.0.
35+
* That is, if the returned value is 0.85, 85% of the max heap is used.
36+
*
37+
* If no max heap is set, the method returns -1.0.
38+
*/
39+
public double getHeapUsage() {
40+
MemoryUsage heapProps = memoryBean.getHeapMemoryUsage();
41+
long heapUsed = heapProps.getUsed();
42+
long heapMax = heapProps.getMax();
43+
44+
if (heapMax == NO_HEAP_LIMIT) {
45+
if (logger.isDebugEnabled()) {
46+
logger.debug("No maximum heap is set");
47+
}
48+
return NO_HEAP_LIMIT;
49+
}
50+
51+
52+
double heapUsage = (double) heapUsed / heapMax;
53+
if (logger.isDebugEnabled()) {
54+
logger.debug("Current heap usage is {0} percent" + (heapUsage * 100));
55+
}
56+
return heapUsage;
57+
}
58+
59+
/**
60+
* see {@link MemoryMXBean#getObjectPendingFinalizationCount()}
61+
*/
62+
public int getObjectPendingFinalizationCount() {
63+
return memoryBean.getObjectPendingFinalizationCount();
64+
}
65+
}

src/flagd/demo.flagd.json

+9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
},
2020
"defaultVariant": "off"
2121
},
22+
"adServiceManualGc": {
23+
"description": "Triggers full manual garbage collections in the ad service",
24+
"state": "ENABLED",
25+
"variants": {
26+
"on": true,
27+
"off": false
28+
},
29+
"defaultVariant": "off"
30+
},
2231
"adServiceFailure": {
2332
"description": "Fail ad service",
2433
"state": "ENABLED",

0 commit comments

Comments
 (0)