Skip to content
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

Allow DAs to customize timeoutsand apps to control logging #1497

Open
wants to merge 26 commits into
base: fdc3-for-web-impl
Choose a base branch
from

Conversation

kriswest
Copy link
Contributor

@kriswest kriswest commented Jan 16, 2025

Describe your change

Resolves two requested additions to getAgent/fdc3-for-web:

  1. Adds the ability to control debug logging output from getAgent() and the DesktopAgentProxy via new arguments to getAgent(). The new arguments are documented in the types and documentation pages.

  2. Allows DesktopAgents to set two custom timeouts, one for most FDC3 for Web message exchanges and a second for message exchanges that involve application launches. Also extends the default timeout for application launch message exchanges to 100 seconds and introduces standardized error messages for ApiTimeout.

Related Issue

resolves #1487
resolves #1488

Contributor License Agreement

  • I acknowledge that a contributor license agreement is required and that I have one in place or will seek to put one in place ASAP.

Review Checklist

  • Issue: If a change was made to the FDC3 Standard, was an issue linked above?
  • CHANGELOG: Is a CHANGELOG.md entry included?
  • API changes: Does this PR include changes to any of the FDC3 APIs (DesktopAgent, Channel, PrivateChannel, Listener, Bridging)?
    • Docs & Sources: If yes, were both documentation (/docs) and sources updated?

      JSDoc comments on interfaces and types should be matched to the main documentation in /docs
    • Conformance tests: If yes, are conformance test definitions (/toolbox/fdc3-conformance) still correct and complete?

      Conformance test definitions should cover all required aspects of an FDC3 Desktop Agent implementation, which are usually marked with a MUST keyword, and optional features (SHOULD or MAY) where the format of those features is defined
    • Schemas: If yes, were changes applied to the Bridging and FDC3 for Web protocol schemas?

      The Web Connection protocol and Desktop Agent Communication Protocol schemas must be able to support all necessary aspects of the Desktop Agent API, while Bridging must support those aspects necessary for Desktop Agents to communicate with each other
      • If yes, was code generation (npm run build) run and the results checked in?

        Generated code will be found at /src/api/BrowserTypes.ts and/or /src/bridging/BridgingTypes.ts

@kriswest kriswest requested a review from robmoffat January 16, 2025 13:03
@kriswest kriswest requested a review from a team as a code owner January 16, 2025 13:03
@kriswest kriswest marked this pull request as draft January 16, 2025 13:03
Copy link

494 passed

Copy link

github-actions bot commented Jan 16, 2025

Coverage Report

Commit: a72c89e
Base: fdc3-for-web-impl@3abc5cb

Type Base This PR
Total Statements Coverage  97.32%  97.38% (+0.06%)
Total Branches Coverage  86.09%  85.93% (-0.16%)
Total Functions Coverage  98.07%  97.89% (-0.18%)
Total Lines Coverage  97.33%  97.41% (+0.08%)
Details (changed files)
FileStatementsBranchesFunctionsLines
packages/fdc3-agent-proxy/src/DesktopAgentProxy.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/index.ts 100% 100% 62.5% 100%
packages/fdc3-agent-proxy/src/apps/DefaultAppSupport.ts 88% 50% 100% 88%
packages/fdc3-agent-proxy/src/channels/DefaultChannel.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/channels/DefaultChannelSupport.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/channels/DefaultPrivateChannel.ts 97.29% 66.66% 100% 97.29%
packages/fdc3-agent-proxy/src/intents/DefaultIntentSupport.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/listeners/AbstractListener.ts 100% 60% 100% 100%
packages/fdc3-agent-proxy/src/listeners/DefaultContextListener.ts 100% 90% 100% 100%
packages/fdc3-agent-proxy/src/listeners/DefaultIntentListener.ts 100% 77.77% 100% 100%
packages/fdc3-agent-proxy/src/listeners/HeartbeatListener.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/listeners/PrivateChannelEventListener.ts 93.33% 72.72% 100% 93.33%
packages/fdc3-agent-proxy/src/messaging/AbstractMessaging.ts 94.59% 100% 80% 94.59%
packages/fdc3-agent-proxy/src/util/AbstractFDC3Logger.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/util/Logger.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/util/throwIfUndefined.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/messaging/MessagePortMessaging.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/messaging/message-port.ts 97.43% 86.66% 100% 97.43%
packages/fdc3-get-agent/src/strategies/FailoverHandler.ts 100% 73.68% 100% 100%
packages/fdc3-get-agent/src/strategies/HelloHandler.ts 94% 81.25% 100% 94%
packages/fdc3-get-agent/src/strategies/PostMessageLoader.ts 98.46% 80% 100% 98.43%
packages/fdc3-get-agent/src/strategies/Timeouts.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/strategies/getAgent.ts 100% 93.33% 100% 100%
packages/fdc3-get-agent/src/util/Logger.ts 100% 100% 100% 100%
packages/fdc3-standard/src/api/Errors.ts 100% 100% 100% 100%
packages/fdc3-standard/src/api/GetAgent.ts 100% 100% 100% 100%
Details (all files)
FileStatementsBranchesFunctionsLines
packages/fdc3-agent-proxy/src/DesktopAgentProxy.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/index.ts 100% 100% 62.5% 100%
packages/fdc3-agent-proxy/src/apps/DefaultAppSupport.ts 88% 50% 100% 88%
packages/fdc3-agent-proxy/src/channels/DefaultChannel.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/channels/DefaultChannelSupport.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/channels/DefaultPrivateChannel.ts 97.29% 66.66% 100% 97.29%
packages/fdc3-agent-proxy/src/heartbeat/DefaultHeartbeatSupport.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/intents/DefaultIntentResolution.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/intents/DefaultIntentSupport.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/listeners/AbstractListener.ts 100% 60% 100% 100%
packages/fdc3-agent-proxy/src/listeners/DefaultContextListener.ts 100% 90% 100% 100%
packages/fdc3-agent-proxy/src/listeners/DefaultIntentListener.ts 100% 77.77% 100% 100%
packages/fdc3-agent-proxy/src/listeners/EventListener.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/listeners/HeartbeatListener.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/listeners/PrivateChannelEventListener.ts 93.33% 72.72% 100% 93.33%
packages/fdc3-agent-proxy/src/messaging/AbstractMessaging.ts 94.59% 100% 80% 94.59%
packages/fdc3-agent-proxy/src/util/AbstractFDC3Logger.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/util/Logger.ts 100% 100% 100% 100%
packages/fdc3-agent-proxy/src/util/throwIfUndefined.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/index.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/messaging/MessagePortMessaging.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/messaging/message-port.ts 97.43% 86.66% 100% 97.43%
packages/fdc3-get-agent/src/sessionStorage/DesktopAgentDetails.ts 97.36% 89.47% 100% 97.36%
packages/fdc3-get-agent/src/strategies/DesktopAgentPreloadLoader.ts 100% 81.25% 100% 100%
packages/fdc3-get-agent/src/strategies/FailoverHandler.ts 100% 73.68% 100% 100%
packages/fdc3-get-agent/src/strategies/HelloHandler.ts 94% 81.25% 100% 94%
packages/fdc3-get-agent/src/strategies/IdentityValidationHandler.ts 95.65% 73.33% 100% 95.65%
packages/fdc3-get-agent/src/strategies/PostMessageLoader.ts 98.46% 80% 100% 98.43%
packages/fdc3-get-agent/src/strategies/Timeouts.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/strategies/getAgent.ts 100% 93.33% 100% 100%
packages/fdc3-get-agent/src/ui/AbstractUIComponent.ts 97.14% 71.42% 100% 97.01%
packages/fdc3-get-agent/src/ui/DefaultDesktopAgentChannelSelector.ts 100% 75% 100% 100%
packages/fdc3-get-agent/src/ui/DefaultDesktopAgentIntentResolver.ts 100% 90% 100% 100%
packages/fdc3-get-agent/src/ui/NullChannelSelector.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/ui/NullIntentResolver.ts 100% 100% 66.66% 100%
packages/fdc3-get-agent/src/util/Logger.ts 100% 100% 100% 100%
packages/fdc3-get-agent/src/util/Uuid.ts 100% 100% 100% 100%
packages/fdc3-standard/src/index.ts 100% 100% 0% 100%
packages/fdc3-standard/src/api/Errors.ts 100% 100% 100% 100%
packages/fdc3-standard/src/api/GetAgent.ts 100% 100% 100% 100%
packages/fdc3-standard/src/api/Methods.ts 94.04% 84.05% 96.29% 95%
packages/fdc3-standard/src/api/RecommendedChannels.ts 100% 100% 100% 100%
packages/fdc3-standard/src/context/ContextType.ts 100% 100% 100% 100%
packages/fdc3-standard/src/intents/Intents.ts 100% 100% 100% 100%
packages/fdc3-standard/src/internal/contextConfiguration.ts 100% 100% 100% 100%
packages/fdc3-standard/src/internal/intentConfiguration.ts 100% 100% 100% 100%
packages/fdc3-standard/src/internal/typeHelpers.ts 100% 100% 100% 100%
toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts 100% 100% 100% 100%
toolbox/fdc3-for-web/fdc3-web-impl/src/ServerContext.ts 100% 100% 100% 100%
toolbox/fdc3-for-web/fdc3-web-impl/src/directory/BasicDirectory.ts 96.87% 84.21% 100% 96.55%
toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/BroadcastHandler.ts 96.38% 86.41% 100% 96.12%
toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/HeartbeatHandler.ts 88.23% 71.87% 86.66% 90%
toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts 95.6% 86.56% 100% 95%
toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/OpenHandler.ts 97.14% 86.84% 100% 97.14%
toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/support.ts 100% 100% 100% 100%

@kriswest kriswest marked this pull request as ready for review January 16, 2025 14:02
@kriswest
Copy link
Contributor Author

@robmoffat I think this and the new tests are working well now.

N.b. I needed to test from the fdc3-get-agent package (although the timeouts are in the fdc3-agent-proxy package) as the custom timeouts are set by the DA in WCP3Handshake responses (which are the province of getAgent()).

@kriswest
Copy link
Contributor Author

kriswest commented Jan 24, 2025

I had to merge the debug logging PR into this one to figure out the tests (needed debug output from the proxy messages).

After doing so I realized that every call to broadcast on the current user channel is preceeded by a call to get the current user channel... I think this should be refined for performance reasons and the current user channel tracked in the channel support - there is, after all, a message sent when the channel is changed... Interested in your thoughts on that @robmoffat.

…r than the app timing it - Desktop Agent should report IntentDelvieryFailed itself)
Copy link

504 passed

@robmoffat
Copy link
Member

Just looking at code coverage, I see cleanup() being called on all the MessageHandelrs except the HeartbeatHandler - any idea why?

type ColorFn = (aString: string) => string;

export abstract class AbstractFDC3Logger {
private static enableDebug: boolean = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really make sense to me that we have two booleans for this behaviour. I think that might be what you're referring to in your slack comment. I think that suggestion is a lot better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you take a closer look at that suggestion - the problem with it is that if you want to be able to disable heartbeat logging separately from other debug logging (and you need to as the heartbeats really get in the way) then we need to move all other logs up to the log level so that debug is just heartbeats so you can turn just them off. Then we'd also want to set the default level above log so that we're not logging every message exchange by default.

If thats ok with you I can action it - but wanted to make sure you understand the implications before I rework it all.

Copy link
Member

@robmoffat robmoffat Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I must admit having re-read it I'm slightly confused about what it all means. Wouldn't it be better to have:

{
  connection: "debug" | "log" | "warn" | "error" | "none"   // I guess some of these levels aren't used.
  proxy: "debug" | "log" | "warn" | "error" | "none" 
  heartbeat: "debug" | "log" | "warn" | "error" | "none" 
}

... so you can choose the level of logging enabled for each part?

Normally, this would be achieved with hierarchical loggers but this is probably overkill here.

Copy link
Contributor Author

@kriswest kriswest Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't make sense to have a level set for heartbeat as its just one log message (that gets printed all. the. time.)...

What I'm suggesting is:

{
  connection: "debug" | "log" | "warn" | "error" | "none"  //default: "log", all levels are used!
  proxy: "debug" | "log" | "warn" | "error" | "none"       //default: "warn", heartbeats at debug, message exchanges at log-level
}

How does that sit with you?

) {
this.heartbeat = heartbeat;
this.intents = intents;
this.channels = channels;
this.apps = apps;
this.connectables = connectables;
Logger.enableHeartbeatLogs(logging.heartbeat);
Logger.enableDebugLogs(logging.debug);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be tidier as Logger.configure(logging)

Copy link
Contributor Author

@kriswest kriswest Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will await a decision on the comment above (using a log level setting instead and moving all messages except heartbeats to above the debug level) first as that would achieve the same.

connectionAttemptUuid: this.connectionAttemptUuid,
handshake: data,
messagePort: event.ports[0],
options: this.options,
actualUrl: globalThis.window.location.href,
agentType: this.agentType,
agentUrl: this.agentUrl ?? undefined,
});
defaultTimeout: data.payload.defaultTimeout ?? DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, it would be better to call this messageExchangeTimeout I think

@@ -5,6 +5,7 @@ import { DesktopAgentSelection, Loader } from './Loader';
import { HelloHandler } from './HelloHandler';
import { IdentityValidationHandler } from './IdentityValidationHandler';
import { Logger } from '../util/Logger';
import { DesktopAgentProxyLogSettings } from '@finos/fdc3-agent-proxy/src/DesktopAgentProxy';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have two different types here?

export type GetAgentLogSettings = {
  connection: boolean;
  connectionDebug: boolean;
  proxyDebug: boolean;
  heartbeat: boolean;
}

and

export type DesktopAgentProxyLogSettings = {
  heartbeat: boolean;
  debug: boolean;
};

It seems like at least two of these overlap, so shouldn't there be type addition happening at the least, if not use of the same type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first is the logging argument to GetAgent which cover both GetAgent and AgentProxy log settings, the second is just that which applies to the proxy (and hence has half the properties). Hence, can't/shouldn't use the same type although they could be unioned, except that the first is in fdc3-standard, the second in downstream implementation projects. All-in-all, meh.

Will decide what to do about it after theres a decision on the log setting.

@@ -0,0 +1,6 @@
/** Default timeout used for all message exchanges with Desktop Agents, except
* those that involve the launch of an application. */
export const DEFAULT_MESSAGE_EXCHANGE_TIMEOUT_MS = 10000;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious that this is here instead of in the getAgent.ts file, since that also has a DEFAULT_TIMEOUT_MS in it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different timeouts - message exchange vs. DA discovery. Changing the name to MESSAGE_EXCHANGE_TIMEOUT_MS (as you suggest) will resolve.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so we end up with all the different default timeouts in the Timeouts.ts file, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see what I can do. The original DEFAULT_TIMEOUT_MS for GetAgent is fdc3-standard/src/GetAgent.ts, while these are in fdc3-get-agent, as they're more implementation related. They should all be cosnilidated - I guess all into fdc3-standard/src/GetAgent.ts and drop Timeouts.ts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, makes sense

@@ -54,6 +54,18 @@
"type": "boolean"
}
]
},
"defaultTimeout": {
"title": "Default Timeout",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah calling this this default timeout to override the default timeout... is pretty confusing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah lets change that to messageExchangeTimeout

packages/testing/src/steps/generic.steps.ts Outdated Show resolved Hide resolved
packages/testing/src/steps/generic.steps.ts Outdated Show resolved Hide resolved
@kriswest
Copy link
Contributor Author

kriswest commented Jan 27, 2025

@robmoffat

Just looking at code coverage, I see cleanup() being called on all the MessageHandelrs except the HeartbeatHandler - any idea why?

The HelloHandler's cleanup function should be getting called but it has no body, just a TODO:

cleanup(_instanceId: InstanceID, _sc: ServerContext<AppRegistration>): void {
//TODO: Consider whether to clean-up last heartbeat times
}

The heartbeatHandler is only created if heartbeats are enabled:
https://github.com/finos/FDC3/blob/fdc3-for-web-impl/toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts/#L79-L82

...and you've got heartbeats disabled in most of the tests, see:

https://github.com/finos/FDC3/blob/fdc3-for-web-impl/toolbox/fdc3-for-web/fdc3-web-impl/test/world/index.ts/#L8-L9

this.server = new DefaultFDC3Server(this.sc, d, defaultChannels(), false, 2000, 2000);

There is one step that enables it:

this.server = new DefaultFDC3Server(this.sc, d, defaultChannels(), true, 2000, 2000);

perhaps you are not shutting down in that one?

Thats all outside the scope of this PR so I'll leave you to look at that. Found a number of other fish that need frying...

@kriswest kriswest changed the title Allow DAs to customize timeouts used for message exchanges and app la… Allow DAs to customize timeoutsand apps to control logging Jan 27, 2025
@kriswest
Copy link
Contributor Author

/netlify

@kriswest
Copy link
Contributor Author

@robmoffat not sure why netlify is ignoring this PR...

@robmoffat
Copy link
Member

@robmoffat not sure why netlify is ignoring this PR...

I can't figure it out! @TheJuanAndOnly99 any ideas?

@kriswest
Copy link
Contributor Author

Closing to re-open (in case that wakes netlify up)

@kriswest kriswest closed this Jan 27, 2025
@kriswest kriswest reopened this Jan 27, 2025
Copy link

504 passed

1 similar comment
Copy link

504 passed

@TheJuanAndOnly99
Copy link
Member

Hey @kriswest @robmoffat If I'm not mistaken Netlify will only generate previews for PRs made against the production branch

@kriswest
Copy link
Contributor Author

@TheJuanAndOnly99 This PR got a preview and was targetting the same (non-main) branch: #1495

...hmm its possible I raised that against main, then changed it... perhaps thats it.

@kriswest kriswest changed the base branch from fdc3-for-web-impl to main January 27, 2025 18:52
@kriswest
Copy link
Contributor Author

/netlify

@kriswest
Copy link
Contributor Author

Switching to main as the base doesn't seem to get going on a build unfortunately. We might be in close and re-open territory.

@robmoffat I'll make the changes to the logging args which should deal with all your comments then open as a new PR?

@kriswest kriswest changed the base branch from main to fdc3-for-web-impl January 27, 2025 18:55
Copy link

504 passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants