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

Cloudwatch metrics #180

Merged
merged 6 commits into from
Jun 28, 2018
Merged

Cloudwatch metrics #180

merged 6 commits into from
Jun 28, 2018

Conversation

rix0rrr
Copy link
Contributor

@rix0rrr rix0rrr commented Jun 26, 2018

Various changes in different commits. Start work on CloudWatch libraries with support for Alarms and Dashboards (the only two CloudWatch entities with a server-side presence).

Expose object model for other libraries to expose metrics. Use those metrics in Lambda and SNS.

Update assertion library with extra matching feature I needed.

Under construction, the README is not done, there are no unit tests for the various metric widgets, no integ tests yet.

By submitting this pull request, I confirm that my contribution is made under
the terms of the beta license.

Rico Huijbers added 4 commits June 26, 2018 16:17
This makes it more flexible to match resources that may have complex
properties. A typical case in which you would need this is if you have
resources that have JSON embedded in a string on which you might want
to do structural matching.
Supports both Alarms and Dashboards. Adds a 'Metric' abstraction
which can be exposed by other resources.
Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

Beautiful! I love everything about this library!


Making Alarms
-------------

Copy link
Contributor

Choose a reason for hiding this comment

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

Missing?

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, I just posted what I had so far to give y'all a chance of shooting at it. Still need to write some sections and add tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also would be nice to document the idiom of construct.metricOfXxx

vertical axes.
- `AlarmWidget` -- shows the graph and alarm line for a single alarm.
- `SingleValueWidget` -- shows the current value of a set of metrics.
- `TextWidget` -- shows some static Markdown.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we call this MarkdownWidget (what's the name used in the CloudWatch docs?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

text, actually. But we're already deviating slightly from their widget structure. I'm okay with calling it MarkdownWidget.

Copy link
Contributor

Choose a reason for hiding this comment

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

So let's stay with text. It's not worth the deviation.

Widgets given in the same call will be laid out horizontally. Widgets given
in different calls will be laid out vertically. To make more complex layouts,
you can use the following widgets to pack widgets together in different ways:

Copy link
Contributor

Choose a reason for hiding this comment

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

I ❤️ this

*/
export interface AlarmProps {
/**
* The metric to add the alarm on
Copy link
Contributor

Choose a reason for hiding this comment

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

A little documentation hint on how to obtain/create metrics

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure

/**
* The number of periods over which data is compared to the specified threshold.
*/
evaluationPeriods: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we provide a sensible default? 1 maybe?

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 suppose. But I kinda feel this is a decision you must consciously make. And 1 is almost never the right answer, I would default to 2 or 3.

Copy link
Contributor

Choose a reason for hiding this comment

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

.... if there is no clear sensible default than I guess we shouldn't provide one... Maybe that's a question for the CW team

title: this.props.title,
region: this.props.region || new AwsRegion(),
annotations: {
alarms: [this.props.alarm.alarmArn]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way for me to add multiple alarms to a graph?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it a use case? Seems like could be easy to add some API to support. But we can wait for the requirement.

*
* @default Average
*/
statistic?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe an enum-like class (already supported in jsii):

class StatisticType {
    static Minimum = new StatisticType('minimum');
    static Average = new StatisticType('average');
    static percentile(x, y = 0) { return new StatisticType(`${x}.{y}`); };
    static P99 = StatisticType.percentile(99);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we can do this, and though in general I hate stringly typing things, I think in this particular case the usability of some well-understood strings is better than those highly modeled objects with long names.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough. So just make sure we have good runtime validation...

}

export interface MetricAlarmJson {
dimensions?: Dimension[];
Copy link
Contributor

Choose a reason for hiding this comment

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

jsdocs

/**
* Name of the dimension
*/
name: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it make more sense to just model this as a simple hash?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For what the user sees, it is a hash. This is internals to type the JSON that we generate for CloudWatch' benefit.

/**
* A single dashboard widget
*/
export interface Widget {
Copy link
Contributor

Choose a reason for hiding this comment

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

IWidget? (I am not sure, but I guess we need a little bit of consistency)

*
* @default average over 5 minutes
*/
public get publishSizeMetric(): Metric {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think metrics should have a common prefix and not a common suffix for discoverabilility and grouping.

return new Metric({
namespace: 'AWS/SNS',
metricName: 'NumberOfMessagesFailed',
dimensions: { TopicName: this.topicName },
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be nice to create have a private method that returns a metric that has namespace and dimensions already set and the these accessors only apply the metric name.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that all of those should actually be methods. Sometimes parameterization will be needed (for example, ElasticCache clusters emit metrics based on the number of shards).

Copy link
Contributor

Choose a reason for hiding this comment

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

And also, this method shouldn’t be private, as an escape hatch in case a new metric is now emitted and the construct doesn’t support it explicitly yes. So I think all constructs should have an “metricOf(name)” and then “metricOfXxxx([params...])” methods

@eladb
Copy link
Contributor

eladb commented Jun 26, 2018

We should also add at least one literate integration test and include it in the README.

Rico Huijbers added 2 commits June 27, 2018 17:38
- Metric providers on resources are now functions.
- Add integration test.
- Add unit tests on graphs.
- Introduce tokenAwareJsonify() which was necessary to properly create a dashboard
  with references to alarms in it.
@rix0rrr rix0rrr merged commit f78561d into master Jun 28, 2018
@rix0rrr rix0rrr deleted the huijbers/cloudwatch-metrics branch June 28, 2018 11:05
* Properties can be:
*
* - An object, in which case its properties will be compared to those of the actual resource found
* - A callablage, in which case it will be treated as a predicate that is applied to the Properties of the found resources.
Copy link
Contributor

Choose a reason for hiding this comment

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

What's a callablage? :)

@NGL321 NGL321 added the contribution/core This is a PR that came from AWS. label Sep 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants