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

Event logger script support: Behavior Context reflection #13596

Merged

Conversation

lemonade-dm
Copy link
Contributor

What does this PR do?

Adding BehaviorContext support for using the EventLogger API

The primary new functions are CreateMetricsLogger, RecordEvent
IsEventLoggerRegistered and GetGlobalEventLoggerFactory.

Several wrapper classes have been added to BehaviorContext to help with
recording event data.
The EventLoggerId class is used to specify an ID for an event logger.
In script it can be created as such

import azlmbr.metrics

eventLoggerId1 = azlmbr.metrics.CreateFromInt(1)
eventLoggerId2 = azlmbr.metrics.CreateFromString("foo")

The EventPhase class is used to specify the type of event to record

import azlmbr.metrics

durationEventPhase = azlmbr.metrics.EventPhase.DurationBegin

The InstantEventScope class is used to specify the scope values to an
InstantEvent.

import azlmbr.metrics

globalScope = azlmbr.metrics.InstantEventScope.Global

The EventValue class is used to create a value that can be appended to
the EventArgs structure for configuring events

import azlmbr.metrics

intValue = azlmbr.emtrics.EventValue(42)
stringValue = azlmbr.metrics.EventValue("Hello world")

The EventArgs class is the primary class used to configure arguments
to record for an event

import azlmbr.metrics

myArgs = azlmbr.metrics.EventArgs()
myArgs.m_name = "Duration Event"
myArgs.m_cat = "Test Category"
myArgs.m_id = "0"
myArgs.AppendArg("Entity Count", 20)
myArgs.AppendArg("Entity Group", "level")

loggerId = azlmbr.metrics.CreateFromString("CustomIdValue")
if azlmbr.metrics.RecordEvent(loggerId, azlmbr.metrics.EventPhase.DurationBegin, myArgs):
    print("Success")

For completeness the CreateMetricsLogger function can be used as
follows

import pathlib
import azlmbr.metrics

loggerId = azlmbr.metrics.CreateFromString("CustomFoo")
outputFilePath = pathlib.Path(azlmbr.paths.projectroot) /
"user/Metrics/MyScriptFoo_metrics.json"
loggerName = "LoggerNameIsFoo"
azlmbr.metrics.CreateMetricsLogger(loggerId, outputFilePath.as_posix(), loggerName)

Other changes include updating the BehaviorContext and BehaviorClass to
have methods for querying a BehaviorClass, BehaviorMethod,
BehaviorProperty, property setter, property getter, or BehaviorEBus via
name.

A Scoped wrapper for the BehaviorObject has been added which
automatically destructs and optionally deallocates objects created by
the Behavior Context.

The BehaviorMethod class has had a IsCallable function which returns a
boolean that indicates if function could be invoked with a given set of
input arguments. If it cannot an outcome with the error message
detailing the reason is returned.

How was this PR tested?

Added C++ UnitTest that verifies the new Behavior Context functions for the EventLogger

Those data types have been reflected to the Behavior Context.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
The primary new functions are `CreateMetricsLogger`, `RecordEvent`
`IsEventLoggerRegistered` and `GetGlobalEventLoggerFactory`.

Several wrapper classes have been added to BehaviorContext to help with
recording event data.
The `EventLoggerId` class is used to specify an ID for an event logger.
In script it can be created as such
```
import azlmbr.metrics

eventLoggerId1 = azlmbr.metrics.CreateFromInt(1)
eventLoggerId2 = azlmbr.metrics.CreateFromString("foo")
```

The `EventPhase` class is used to specify the type of event to record
```
import azlmbr.metrics

durationEventPhase = azlmbr.metrics.EventPhase.DurationBegin
```

The `InstantEventScope` class is used to specify the scope values to an
InstantEvent.
```
import azlmbr.metrics

globalScope = azlmbr.metrics.InstantEventScope.Global
```

The `EventValue` class is used to create a value that can be appended to
the `EventArgs` structure for configuring events
```
import azlmbr.metrics

intValue = azlmbr.emtrics.EventValue(42)
stringValue = azlmbr.metrics.EventValue("Hello world")
```

The `EventArgs` class is the primary class used to configure arguments
to record for an event
```
import azlmbr.metrics

myArgs = azlmbr.metrics.EventArgs()
myArgs.m_name = "Duration Event"
myArgs.m_cat = "Test Category"
myArgs.m_id = "0"
myArgs.AppendArg("Entity Count", 20)
myArgs.AppendArg("Entity Group", "level")

loggerId = azlmbr.metrics.CreateFromString("CustomIdValue")
if azlmbr.metrics.RecordEvent(loggerId, azlmbr.metrics.EventPhase.DurationBegin, myArgs):
    print("Success")

```

For completeness the `CreateMetricsLogger` function can be used as
follows
```
import pathlib
import azlmbr.metrics

loggerId = azlmbr.metrics.CreateFromString("CustomFoo")
outputFilePath = pathlib.Path(azlmbr.paths.projectroot) /
"user/Metrics/MyScriptFoo_metrics.json"
loggerName = "LoggerNameIsFoo"
azlmbr.metrics.CreateMetricsLogger(loggerId, outputFilePath.as_posix(), loggerName)
```

Other changes include updating the BehaviorContext and BehaviorClass to
have methods for querying a BehaviorClass, BehaviorMethod,
BehaviorProperty, property setter, property getter, or BehaviorEBus via
name.

A Scoped wrapper for the BehaviorObject has been added which
automatically destructs and optionally deallocates objects created by
the Behavior Context.

The BehaviorMethod class has had a IsCallable function which returns a
boolean that indicates if function could be invoked with a given set of
input arguments. If it cannot an outcome with the error message
detailing the reason is returned.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
Copy link
Contributor

@lsemp3d lsemp3d left a comment

Choose a reason for hiding this comment

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

Just a few minor things


namespace AZ::Metrics
{
// Utility namespace contains functions/class to simpilfy calls to record events
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: simpilfy

/**
* Use this macro outside a class to allow it to be identified across modules and serialized (in different contexts).
* The expected input is the class and the assigned uuid as a string or an instance of a uuid.
* Note that the AZ_TYPE_INFO_SPECIALIZE always has be declared in "namespace AZ".
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* Note that the AZ_TYPE_INFO_SPECIALIZE always has be declared in "namespace AZ".
* Note that the AZ_TYPE_INFO_SPECIALIZE always has to be declared in "namespace AZ".

Comment on lines 1294 to 1312
AZ_TYPE_INFO_SPECIALIZE(char, "{3AB0037F-AF8D-48ce-BCA0-A170D18B2C03}");
// AZ_TYPE_INFO_SPECIALIZE(signed char, "{CFD606FE-41B8-4744-B79F-8A6BD97713D8}");
AZ_TYPE_INFO_SPECIALIZE(AZ::s8, "{58422C0E-1E47-4854-98E6-34098F6FE12D}");
AZ_TYPE_INFO_SPECIALIZE(short, "{B8A56D56-A10D-4dce-9F63-405EE243DD3C}");
AZ_TYPE_INFO_SPECIALIZE(int, "{72039442-EB38-4d42-A1AD-CB68F7E0EEF6}");
AZ_TYPE_INFO_SPECIALIZE(long, "{8F24B9AD-7C51-46cf-B2F8-277356957325}");
AZ_TYPE_INFO_SPECIALIZE(AZ::s64, "{70D8A282-A1EA-462d-9D04-51EDE81FAC2F}");
AZ_TYPE_INFO_SPECIALIZE(unsigned char, "{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}");
AZ_TYPE_INFO_SPECIALIZE(unsigned short, "{ECA0B403-C4F8-4b86-95FC-81688D046E40}");
AZ_TYPE_INFO_SPECIALIZE(unsigned int, "{43DA906B-7DEF-4ca8-9790-854106D3F983}");
AZ_TYPE_INFO_SPECIALIZE(unsigned long, "{5EC2D6F7-6859-400f-9215-C106F5B10E53}");
AZ_TYPE_INFO_SPECIALIZE(AZ::u64, "{D6597933-47CD-4fc8-B911-63F3E2B0993A}");
AZ_TYPE_INFO_SPECIALIZE(float, "{EA2C3E90-AFBE-44d4-A90D-FAAF79BAF93D}");
AZ_TYPE_INFO_SPECIALIZE(double, "{110C4B14-11A8-4e9d-8638-5051013A56AC}");
AZ_TYPE_INFO_SPECIALIZE(bool, "{A0CA880C-AFE4-43cb-926C-59AC48496112}");
AZ_TYPE_INFO_SPECIALIZE(AZ::Uuid, "{E152C105-A133-4d03-BBF8-3D4B2FBA3E2A}");
AZ_TYPE_INFO_SPECIALIZE(void, "{C0F1AFAD-5CB3-450E-B0F5-ADB5D46B0E22}");
AZ_TYPE_INFO_SPECIALIZE(Crc32, "{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}");
AZ_TYPE_INFO_SPECIALIZE(PlatformID, "{0635D08E-DDD2-48DE-A7AE-73CC563C57C3}");
AZ_TYPE_INFO_SPECIALIZE(AZStd::monostate, "{B1E9136B-D77A-4643-BE8E-2ABDA246AE0E}");
Copy link
Contributor

Choose a reason for hiding this comment

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

What happened here? they were deleted and restored? Also, signed char is commented out, remove?

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 macro was changed from using AZ_TYPE_INFO_INTERNAL_SPECIALIZE to the public AZ_TYPE_INFO_SPECIALIZE.

The signed char was commented out before and remains commented out. I can remove it.

auto classIter = m_behaviorContext->m_classes.find(EventValueClassName);
EXPECT_NE(m_behaviorContext->m_classes.end(), classIter);

classIter = m_behaviorContext->m_classes.find("EventLoggerId");
Copy link
Contributor

Choose a reason for hiding this comment

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

A few lines above here you constexpr const char* define EventValue, EventField and others. Any reason not to do the same for EventLoggerId, EventArgs, etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No reason not to. I can add constants to all of them.

The EventLogger creation function will be now be queued after the
TickBus has turned back on function queuing.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
@lemonade-dm lemonade-dm requested a review from a team as a code owner December 8, 2022 17:55
The EventLoggerReflectUtilsTests now reference class, methods and
property names using `const char*` constants.

Removed unneccessary `typename` keyword usage in the new IsCallable
functions to fix clange build errors.

Removed commented out `signed char` AZ_TYPE_INFO_SPECIALIZE call.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
The BehaviorHandlerFactoryMethod, ScriptBroadcastMethod, and ScriptEventBroadcast have been updated to implement the `Call` function which accepts a span parameter and to implement the new `IsCallable` function.

This fixes the compiler errors due to be being an abstract class.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
@lemonade-dm lemonade-dm merged commit b34908f into o3de:development Dec 12, 2022
@lemonade-dm lemonade-dm deleted the event-logger-script-support branch December 12, 2022 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants