-
Notifications
You must be signed in to change notification settings - Fork 4
Introduce debugs logs for ease the troubleshooting efforts #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
348b0b2
7fb869f
1c280ed
4a32100
9f7c2ce
027d340
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,7 +30,7 @@ http:Service consolidatorService = service object { | |||||||||
| topics: getTopics(), | ||||||||||
| subscriptions: getSubscriptions() | ||||||||||
| }; | ||||||||||
| log:printInfo("Request received to retrieve state-snapshot, hence responding with the current state-snapshot", state = stateSnapshot); | ||||||||||
| log:printDebug("Request received to retrieve state-snapshot, hence responding with the current state-snapshot", state = stateSnapshot); | ||||||||||
| return stateSnapshot; | ||||||||||
| } | ||||||||||
| }; | ||||||||||
|
|
@@ -39,46 +39,74 @@ isolated function consolidateSystemState() returns error? { | |||||||||
| do { | ||||||||||
| while true { | ||||||||||
| kafka:BytesConsumerRecord[] records = check conn:websubEventConsumer->poll(config:kafka.consumer.pollingInterval); | ||||||||||
| log:printDebug("Polled Kafka records for state consolidation", recordCount = records.length(), pollingInterval = config:kafka.consumer.pollingInterval); | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have any computation, it's better to use a function pointer, as it is only executed when we enable the debug level. Otherwise, it has unnecessary tasks. log:printDebug("Polled Kafka records for state consolidation",
recordCount = isolated function() returns int { return records.length();},
pollingInterval = config:kafka.consumer.pollingInterval); |
||||||||||
|
|
||||||||||
| if records.length() > 0 { | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 3
Suggested change
|
||||||||||
| log:printDebug("Processing batch of Kafka records", batchSize = records.length()); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| foreach kafka:BytesConsumerRecord currentRecord in records { | ||||||||||
| string lastPersistedData = check string:fromBytes(currentRecord.value); | ||||||||||
| int messageSize = lastPersistedData.length(); | ||||||||||
| log:printDebug("Processing Kafka record for consolidation", messageSize = messageSize, offset = currentRecord.offset); | ||||||||||
|
Comment on lines
+50
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can do the same as above without initializing the variable. |
||||||||||
| error? result = processPersistedData(lastPersistedData); | ||||||||||
| if result is error { | ||||||||||
| log:printError("Error occurred while processing received event ", 'error = result); | ||||||||||
| common:logError("Error occurred while processing received event ", result); | ||||||||||
| } else { | ||||||||||
| log:printDebug("Successfully processed Kafka record", offset = currentRecord.offset); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } on fail var e { | ||||||||||
| log:printDebug("Error in consolidation loop, closing Kafka consumer", gracePeriod = config:kafka.consumer.gracefulClosePeriod); | ||||||||||
| _ = check conn:websubEventConsumer->close(config:kafka.consumer.gracefulClosePeriod); | ||||||||||
| return e; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| isolated function processPersistedData(string persistedData) returns error? { | ||||||||||
| log:printDebug("Starting persisted data processing", dataSize = persistedData.length()); | ||||||||||
|
|
||||||||||
| json payload = check value:fromJsonString(persistedData); | ||||||||||
| string hubMode = check payload.hubMode; | ||||||||||
| log:printDebug("Processing event based on hub mode", hubMode = hubMode); | ||||||||||
|
|
||||||||||
| match hubMode { | ||||||||||
| "register" => { | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 4
Suggested change
|
||||||||||
| log:printDebug("Processing topic registration event"); | ||||||||||
| check processTopicRegistration(payload); | ||||||||||
| log:printDebug("Topic registration event processed successfully"); | ||||||||||
| } | ||||||||||
| "deregister" => { | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 5
Suggested change
|
||||||||||
| log:printDebug("Processing topic deregistration event"); | ||||||||||
| check processTopicDeregistration(payload); | ||||||||||
| log:printDebug("Topic deregistration event processed successfully"); | ||||||||||
| } | ||||||||||
| "subscribe" => { | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 6
Suggested change
|
||||||||||
| log:printDebug("Processing subscription event"); | ||||||||||
| check processSubscription(payload); | ||||||||||
| log:printDebug("Subscription event processed successfully"); | ||||||||||
| } | ||||||||||
| "unsubscribe" => { | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 7
Suggested change
|
||||||||||
| log:printDebug("Processing unsubscription event"); | ||||||||||
| check processUnsubscription(payload); | ||||||||||
| log:printDebug("Unsubscription event processed successfully"); | ||||||||||
| } | ||||||||||
| _ => { | ||||||||||
| common:logError("Invalid hub mode received", hubMode = hubMode); | ||||||||||
| return error(string `Error occurred while deserializing subscriber events with invalid hubMode [${hubMode}]`); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| log:printDebug("Completed processing persisted data", hubMode = hubMode); | ||||||||||
| } | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 8
Suggested change
|
||||||||||
|
|
||||||||||
| isolated function processStateUpdate() returns error? { | ||||||||||
| log:printDebug("Processing state update - gathering current system state"); | ||||||||||
| common:SystemStateSnapshot stateSnapshot = { | ||||||||||
| topics: getTopics(), | ||||||||||
| subscriptions: getSubscriptions() | ||||||||||
| }; | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 9
Suggested change
|
||||||||||
| log:printDebug("Created state snapshot for persistence", topicCount = stateSnapshot.topics.length(), subscriptionCount = stateSnapshot.subscriptions.length()); | ||||||||||
| check persist:persistWebsubEventsSnapshot(stateSnapshot); | ||||||||||
| log:printDebug("State snapshot persisted successfully"); | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -18,13 +18,19 @@ import websubhub.consolidator.common; | |||||||||||||
| import websubhub.consolidator.config; | ||||||||||||||
| import websubhub.consolidator.connections as conn; | ||||||||||||||
|
|
||||||||||||||
| import ballerina/log; | ||||||||||||||
|
|
||||||||||||||
| public isolated function persistWebsubEventsSnapshot(common:SystemStateSnapshot systemStateSnapshot) returns error? { | ||||||||||||||
| log:printDebug("Persisting system state snapshot", topicCount = systemStateSnapshot.topics.length(), subscriptionCount = systemStateSnapshot.subscriptions.length()); | ||||||||||||||
|
Comment on lines
23
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 11
Suggested change
|
||||||||||||||
| json payload = systemStateSnapshot.toJson(); | ||||||||||||||
| check produceKafkaMessage(config:state.snapshot.topic, payload); | ||||||||||||||
| log:printDebug("System state snapshot persisted successfully", targetTopic = config:state.snapshot.topic); | ||||||||||||||
|
Comment on lines
26
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 12
Suggested change
|
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| isolated function produceKafkaMessage(string topicName, json payload) returns error? { | ||||||||||||||
| log:printDebug("Producing Kafka message", targetTopic = topicName); | ||||||||||||||
|
Comment on lines
30
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 13
Suggested change
|
||||||||||||||
| byte[] serializedContent = payload.toJsonString().toBytes(); | ||||||||||||||
| check conn:statePersistProducer->send({topic: topicName, value: serializedContent}); | ||||||||||||||
| check conn:statePersistProducer->'flush(); | ||||||||||||||
| log:printDebug("Message successfully sent to Kafka", topic = topicName); | ||||||||||||||
| } | ||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,54 +16,63 @@ | |||||||||
|
|
||||||||||
| import websubhub.consolidator.common; | ||||||||||
|
|
||||||||||
| import ballerina/lang.value; | ||||||||||
| import ballerina/log; | ||||||||||
| import ballerina/websubhub; | ||||||||||
|
|
||||||||||
| isolated map<websubhub:VerifiedSubscription> subscribersCache = {}; | ||||||||||
|
|
||||||||||
| isolated function deSerializeSubscribersMessage(string lastPersistedData) returns websubhub:VerifiedSubscription[]|error { | ||||||||||
| websubhub:VerifiedSubscription[] currentSubscriptions = []; | ||||||||||
| json[] payload = <json[]>check value:fromJsonString(lastPersistedData); | ||||||||||
| foreach var data in payload { | ||||||||||
| websubhub:VerifiedSubscription subscription = check data.cloneWithType(websubhub:VerifiedSubscription); | ||||||||||
| currentSubscriptions.push(subscription); | ||||||||||
| } | ||||||||||
| return currentSubscriptions; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| isolated function refreshSubscribersCache(websubhub:VerifiedSubscription[] persistedSubscribers) { | ||||||||||
| log:printDebug("Refreshing subscribers cache from persisted data", persistedSubscriberCount = persistedSubscribers.length()); | ||||||||||
|
Comment on lines
24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 14
Suggested change
|
||||||||||
| foreach var subscriber in persistedSubscribers { | ||||||||||
| string groupName = common:generatedSubscriberId(subscriber.hubTopic, subscriber.hubCallback); | ||||||||||
| lock { | ||||||||||
| subscribersCache[groupName] = subscriber.cloneReadOnly(); | ||||||||||
| } | ||||||||||
| log:printDebug("Added subscriber to cache during refresh", subscriberId = groupName, topic = subscriber.hubTopic, callback = subscriber.hubCallback); | ||||||||||
| } | ||||||||||
| log:printDebug("Subscribers cache refresh completed", totalCachedSubscribers = subscribersCache.length()); | ||||||||||
|
Comment on lines
32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 15
Suggested change
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| isolated function processSubscription(json payload) returns error? { | ||||||||||
| log:printDebug("Processing subscription event"); | ||||||||||
| websubhub:VerifiedSubscription subscription = check payload.cloneWithType(websubhub:VerifiedSubscription); | ||||||||||
| string subscriberId = common:generatedSubscriberId(subscription.hubTopic, subscription.hubCallback); | ||||||||||
| log:printDebug("Deserialized subscription", subscriberId = subscriberId, topic = subscription.hubTopic, callback = subscription.hubCallback); | ||||||||||
| boolean subscriptionAdded = false; | ||||||||||
| lock { | ||||||||||
| // add the subscriber if subscription event received | ||||||||||
| if !subscribersCache.hasKey(subscriberId) { | ||||||||||
| subscribersCache[subscriberId] = subscription.cloneReadOnly(); | ||||||||||
| subscriptionAdded = true; | ||||||||||
| log:printDebug("Added new subscription to cache", subscriberId = subscriberId, totalSubscriptions = subscribersCache.length()); | ||||||||||
| } else { | ||||||||||
| log:printDebug("Subscription already exists in cache, skipping", subscriberId = subscriberId); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| check processStateUpdate(); | ||||||||||
| log:printDebug("Subscription processing completed", subscriberId = subscriberId, wasAdded = subscriptionAdded); | ||||||||||
|
Comment on lines
52
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 16
Suggested change
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| isolated function processUnsubscription(json payload) returns error? { | ||||||||||
| log:printDebug("Processing unsubscription event"); | ||||||||||
| websubhub:VerifiedUnsubscription unsubscription = check payload.cloneWithType(websubhub:VerifiedUnsubscription); | ||||||||||
| string subscriberId = common:generatedSubscriberId(unsubscription.hubTopic, unsubscription.hubCallback); | ||||||||||
| log:printDebug("Deserialized unsubscription", subscriberId = subscriberId, topic = unsubscription.hubTopic, callback = unsubscription.hubCallback); | ||||||||||
| lock { | ||||||||||
| // remove the subscriber if the unsubscription event received | ||||||||||
| _ = subscribersCache.removeIfHasKey(subscriberId); | ||||||||||
| websubhub:VerifiedSubscription? removedSubscription = subscribersCache.removeIfHasKey(subscriberId); | ||||||||||
| boolean subscriptionRemoved = removedSubscription is websubhub:VerifiedSubscription; | ||||||||||
| log:printDebug("Removed subscription from cache", subscriberId = subscriberId, wasRemoved = subscriptionRemoved, totalSubscriptions = subscribersCache.length()); | ||||||||||
|
Comment on lines
+63
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||||||||||
| } | ||||||||||
| check processStateUpdate(); | ||||||||||
| log:printDebug("Unsubscription processing completed", subscriberId = subscriberId); | ||||||||||
|
Comment on lines
67
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 17
Suggested change
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| isolated function getSubscriptions() returns websubhub:VerifiedSubscription[] { | ||||||||||
| websubhub:VerifiedSubscription[] subscriptions; | ||||||||||
| lock { | ||||||||||
| return subscribersCache.toArray().cloneReadOnly(); | ||||||||||
| subscriptions = subscribersCache.toArray().cloneReadOnly(); | ||||||||||
| } | ||||||||||
| log:printDebug("Retrieved subscriptions from cache", subscriptionCount = subscriptions.length()); | ||||||||||
| return subscriptions; | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,38 +15,55 @@ | |||||||||||||||||||||||||||
| // under the License. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| import ballerina/lang.value; | ||||||||||||||||||||||||||||
| import ballerina/log; | ||||||||||||||||||||||||||||
| import ballerina/websubhub; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| isolated map<websubhub:TopicRegistration> registeredTopicsCache = {}; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| isolated function refreshTopicCache(websubhub:TopicRegistration[] persistedTopics) { | ||||||||||||||||||||||||||||
| log:printDebug("Refreshing topic cache from persisted data", persistedTopicCount = persistedTopics.length()); | ||||||||||||||||||||||||||||
|
Comment on lines
23
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 19
Suggested change
|
||||||||||||||||||||||||||||
| foreach var topic in persistedTopics.cloneReadOnly() { | ||||||||||||||||||||||||||||
| lock { | ||||||||||||||||||||||||||||
| registeredTopicsCache[topic.topic] = topic.cloneReadOnly(); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| log:printDebug("Added topic to cache during refresh", topicName = topic.topic); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
25
to
30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 18
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Topic cache refresh completed", totalCachedTopics = registeredTopicsCache.length()); | ||||||||||||||||||||||||||||
|
Comment on lines
30
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 20
Suggested change
|
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| isolated function processTopicRegistration(json payload) returns error? { | ||||||||||||||||||||||||||||
|
Comment on lines
33
to
34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 21
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Processing topic registration event"); | ||||||||||||||||||||||||||||
| websubhub:TopicRegistration registration = check value:cloneWithType(payload); | ||||||||||||||||||||||||||||
|
Comment on lines
+35
to
36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 22
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Deserialized topic registration", topicName = registration.topic); | ||||||||||||||||||||||||||||
| lock { | ||||||||||||||||||||||||||||
| // add the topic if topic-registration event received | ||||||||||||||||||||||||||||
| registeredTopicsCache[registration.topic] = registration.cloneReadOnly(); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
40
to
41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 23
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Added topic to cache", topicName = registration.topic, totalTopics = registeredTopicsCache.length()); | ||||||||||||||||||||||||||||
| check processStateUpdate(); | ||||||||||||||||||||||||||||
|
Comment on lines
+42
to
43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 24
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Topic registration processing completed", topicName = registration.topic); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| isolated function processTopicDeregistration(json payload) returns error? { | ||||||||||||||||||||||||||||
|
Comment on lines
46
to
47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 25
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Processing topic deregistration event"); | ||||||||||||||||||||||||||||
| websubhub:TopicDeregistration deregistration = check value:cloneWithType(payload); | ||||||||||||||||||||||||||||
|
Comment on lines
+48
to
49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 26
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Deserialized topic deregistration", topicName = deregistration.topic); | ||||||||||||||||||||||||||||
| boolean topicRemoved = false; | ||||||||||||||||||||||||||||
| lock { | ||||||||||||||||||||||||||||
| // remove the topic if topic-deregistration event received | ||||||||||||||||||||||||||||
| _ = registeredTopicsCache.removeIfHasKey(deregistration.topic); | ||||||||||||||||||||||||||||
| websubhub:TopicRegistration? removedTopic = registeredTopicsCache.removeIfHasKey(deregistration.topic); | ||||||||||||||||||||||||||||
| topicRemoved = removedTopic is websubhub:TopicRegistration; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+55
to
56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 27
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Removed topic from cache", topicName = deregistration.topic, wasRemoved = topicRemoved, totalTopics = registeredTopicsCache.length()); | ||||||||||||||||||||||||||||
| check processStateUpdate(); | ||||||||||||||||||||||||||||
|
Comment on lines
+57
to
58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 28
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Topic deregistration processing completed", topicName = deregistration.topic); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| isolated function getTopics() returns websubhub:TopicRegistration[] { | ||||||||||||||||||||||||||||
| websubhub:TopicRegistration[] topics; | ||||||||||||||||||||||||||||
| lock { | ||||||||||||||||||||||||||||
| return registeredTopicsCache.toArray().cloneReadOnly(); | ||||||||||||||||||||||||||||
| topics = registeredTopicsCache.toArray().cloneReadOnly(); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+65
to
66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log Improvement Suggestion No: 29
Suggested change
|
||||||||||||||||||||||||||||
| log:printDebug("Retrieved topics from cache", topicCount = topics.length()); | ||||||||||||||||||||||||||||
| return topics; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 1