Deploying AWS Cloudwatch dashboards with the CDK: how do I hide metrics - amazon-cloudwatch

I have a custom metric that I push updates to in my code. In the CDK, I have created a derived metric from this custom metric. I would like the derived metric to show up in the dashboard but the original metric to be hidden. How can I achieve this?
Here is my cut-down (TypeScript) CDK code which deploys successfully:
const createDashboard = (scope: cdk.Construct, namespace: string, statistic = Statistic.AVERAGE) => {
const customDynamoLatencyMetric: IMetric = new Metric({
period: Duration.minutes(1),
metricName: 'MY_DYNAMO_LATENCY_METRIC',
namespace,
statistic,
});
const derivedAverageDynamoLatencyMetric = new MathExpression({
expression: 'm1/1000', label: 'To Dynamo Latency', usingMetrics: { m1: customDynamoLatencyMetric }, period: Duration.minutes(1),
});
const dashboard = new Dashboard(
scope,
'myDashboard', {
dashboardName: 'myDashboard',
},
);
const widget = new GraphWidget({
title: 'Average Latency',
left: [customDynamoLatencyMetric, derivedAverageDynamoLatencyMetric],
view: GraphWidgetView.TIME_SERIES,
region: AWS_DEFAULT_REGION,
width: 12,
});
dashboard.addWidgets(widget);
};
If I manually mark this metric as invisible in the AWS Cloudwatch Dasgboard Console then when I view/edit source in the Cloudwatch Console I see the following:
"metrics": [
[ "stephenburns-gcs-pipeline", "DYNAMO_LATENCY", { "id": "m1", "visible": false } ],
[ { "label": "To Dynamo Latency", "expression": "m1/1000", "period": 60, "id": "e1", "region": "ap-southeast-2" } ]
]
My question is how do I get that "visible": false property via the CDK?
I tried using the Metric's dimensions property e.g.
dimensions: { visible: false }
but it fails at deployment time with the error: "Invalid metric field type, only "String" type is allowed"
Does anyone know how to mark a metric as initially invisible?

If you only add the original Metric to the usingMetrics property of the MathExpression and don't add it directly to the GraphWidget, the CDK appears to automatically set visible to false. The CDK documentation does not currently (as of version 1.123.0) indicate a way to set the visibility of a Metric directly.
In the code example you provided, this would simply require changing the line:
left: [customDynamoLatencyMetric, derivedAverageDynamoLatencyMetric],
to:
left: [customDynamoLatencyMetric],

Related

Converting AWS CloudWatch Metrics Insight query to CDK Metric

I am modifying the sample at https://github.com/cdk-patterns/serverless/tree/main/the-eventbridge-etl/typescript as I want to add a dashboard widget to my CloudFormation Stack that shows the Fargate vCPU usage. I have been able to upgrade the app to use CDK v2, and deployment/functionality has been confirmed. However, I cannot get the vCPU widget in the dashboard to show any data.
If I configure the widget manually, from within AWS CloudWatch's Source field, the query looks as follows:
{
"metrics": [
[ { "expression": "SELECT COUNT(ResourceCount) FROM SCHEMA(\"AWS/Usage\", Class,Resource,Service,Type) WHERE Service = 'Fargate' AND Resource = 'vCPU'", "label": "Query1", "id": "q1" } ],
[ "AWS/Usage", "ResourceCount", "Service", "Fargate", "Type", "Resource", { "id": "m1" } ]
],
"view": "timeSeries",
"title": "ExtractECSJob",
"region": "us-west-2",
"timezone": "Local",
"stat": "Sum",
"period": 300
}
However, when I attempt to use CDK, with the following TypeScript code:
const extractECSWidget = new GraphWidget({
title: "ExtractECSJob",
left: [
new Metric({
namespace: "AWS/Usage",
metricName: "ResourceCount",
statistic: "Sum",
period: Duration.seconds(300),
dimensionsMap: {
"Service": "Fargate",
"Type": "Resource",
"Resource": "vCPU"
}
})
]
});
This does not translate to the above, and no information is shown in this widget. The new source looks as follows:
{
"view": "timeSeries",
"title": "ExtractECSJob",
"region": "us-west-2",
"metrics": [
[ "AWS/Usage", "ResourceCount", "Resource", "vCPU", "Service", "Fargate", "Type", "Resource", { "stat": "Sum" } ]
],
"period": 300
}
How do I map the above metrics source definition to the CDK source construct?
I tried using MathExpression but with the following:
let metrics = new MathExpression({
expression: "SELECT COUNT('metricName') FROM SCHEMA('\"AWS/Usage\"', 'Class','Resource','Service','Type') WHERE Service = 'Fargate' AND Resource = 'vCPU'",
usingMetrics: {}
})
const extractECSWidget = new GraphWidget({
title: "ExtractECSJob",
left: [
metrics
]
});
I get the warning during cdk diff:
[Warning at /EventbridgeEtlStack/EventBridgeETLDashboard] Math expression 'SELECT COUNT(metricName) FROM SCHEMA($namespace, Class,Resource,Service,Type) WHERE Service = 'Fargate' AND Resource = 'vCPU'' references unknown identifiers: metricName, namespace, lass, esource, ervice, ype, ervice, argate, esource, vCPU. Please add them to the 'usingMetrics' map.
What should I put in the usingMetrics map? Any help is appreciated.
Thanks to AWS Support I was able to have this fixed. The updated code looks like the following:
let metrics = new MathExpression({
expression: "SELECT COUNT(ResourceCount) FROM SCHEMA(\"AWS/Usage\", Class,Resource,Service,Type) WHERE Service = 'Fargate' AND Resource = 'vCPU'",
usingMetrics: {},
label: "Query1"
})
let metric2 = new Metric({
namespace: "AWS/Usage",
metricName: "ResourceCount",
period: cdk.Duration.seconds(300),
dimensionsMap: {
"Service": "Fargate",
"Type": "Resource",
}
})
const extractECSWidget = new GraphWidget({
title: "ExtractECSJobTest",
left: [metrics, metric2],
region: "us-west-2",
statistic: "Sum",
width: 24
});
dashboardStack.addWidgets(
extractECSWidget
);
When running cdk deploy, I still get the same warning (about unknown identifiers being referenced) but the widget is functioning as expected.
This feature has not been supported by CDK yet. I've opened the issue https://github.com/aws/aws-cdk/issues/22844
I faced the same issue while creating an alarm based on a metric based on a query. I found the workaround with level 1 construct CfnAlarm
Maybe same kind of workaround exists for Widget.

Define a condition in cloudformation template with alarms

How to define/declare a condition to create an alarm in prod?
With the condition:Isprod would work to create an alarm in prod?
WOULD this work? how to define a condition below?
LambdaInvocationsAlarm:
Condition: IsProd
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Lambda invocations
AlarmName: LambdaInvocationsAlarm
ComparisonOperator: LessThanLowerOrGreaterThanUpperThreshold
EvaluationPeriods: 1
Metrics:
- Expression: ANOMALY_DETECTION_BAND(m1, 2)
Id: ad1
- Id: m1
MetricStat:
Metric:
MetricName: Invocations
Namespace: AWS/Lambda
Period: !!int 86400
Stat: Sum
ThresholdMetricId: ad1
TreatMissingData: breaching
As #Marcin said, you should explain what you have tried and what is blocking more precisely.
But what you suggest could work yes: you can define a Condition named isProd and use it to create - or not - resources. Regarding this condition: AWS does not know what is a production stage in your environment, so you need to specify that. Does your production stage matches an account? Does it match a region? Something else?
As an example and if we assume that your production stage matches a specific AWS account, then you could define the condition as below (it's JSON, feel free to convert to YAML):
{
"Parameters": {
"ProdAccountParameter": {
"Type": "String",
"Description": "Enter the production account identifier."
}
},
"Conditions": {
"isProd": {
"Fn::Equals": [
{
"Ref": "ProdAccountParameter"
},
{
"Ref": "AWS::AccountId"
}
]
}
},
...
}
(Then, when deploying the template, you'll need to provide your AWS production account).

docusaurus about sidebars of docusaurus to multi-language

I use 'Docusaurus' to docs but I don`t know How to config multi-language sideBar.
[
'#docusaurus/preset-classic',
{
docs: {
path: 'docs',
routeBasePath: '/',
sidebarPath: require.resolve('./sidebars.js')
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
]```
The code only use a kind of sidebars, if I switch the language The sidebars can`t switch.
run the write-translations command, for example your locale is zh-cn, when command finished, you will get a current.json file in the i18n/zh-cn/docusaurus-plugin-content-docs directory
yarn run write-translations -- --locale zh-cn
the current.json contains the docs sidebar's category labels, modify it like the following:
{
"version.label": {
"message": "5.0.0.alpha.1",
"description": "The label for version current"
},
"sidebar.docsSidebar.category.Getting Started": {
"message": "开始上手",
"description": "The label for category Getting Started in sidebar docsSidebar"
},
"sidebar.docsSidebar.category.Guides": {
"message": "指南",
"description": "The label for category Guides in sidebar docsSidebar"
}
}
for more details, refer to:https://docusaurus.io/docs/next/i18n/tutorial#translate-plugin-data
Docusaurus allows you to add a navbar item so the user can select the language they want. You can enable the dropdown by adding the code below, as explained in the official documentation, to the docusaurus.config.js file.
If you want to find out more you can also have a look at this video in which I explain all the steps you need to follow to translate your Docusaurus website.
module.exports = {
themeConfig: {
navbar: {
items: [
{
type: 'localeDropdown',
position: 'left',
},
],
},
},
};
if I switch the language The sidebars can`t switch
If you properly prepared i18n JSON files, when you switch the locale (language), the sidebar label will show different languages.

How to use input transformer for ECS Fargate launch type with Terraform CloudWatch event trigger

I'm using terraform to create a CloudWatch Event Trigger with a ECS Fargate launch type which the event source is S3. When I use the input_transformer field to pass in the bucket and key into the ECS task, my event rule results in a failed invocation.
This is the aws_cloudwatch_event_rule:
resource "aws_cloudwatch_event_rule" "event_rule" {
name = "dev-gnss-source-put-rule-tf"
description = "Capture S3 events on uploads bucket"
event_pattern = <<PATTERN
{
"source": [
"aws.s3"
],
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"s3.amazonaws.com"
],
"eventName": [
"PutObject"
],
"requestParameters": {
"bucketName": [
"example-bucket-name"
]
}
}
}
PATTERN
}
This is the aws_cloudwatch_event_target:
resource "aws_cloudwatch_event_target" "event_target" {
target_id = "dev-gnss-upload-event-target-tf"
arn = "example-cluster-arn"
rule = aws_cloudwatch_event_rule.event_rule.name
role_arn = aws_iam_role.uploads_events.arn
ecs_target {
launch_type = "FARGATE"
task_count = 1 # Launch one container / event
task_definition_arn = "example-task-definition-arn"
network_configuration {
subnets = ["example-subnet"]
security_groups = []
}
}
input_transformer {
input_paths = {
s3_bucket = "$.detail.requestParameters.bucketName"
s3_key = "$.detail.requestParameters.key"
}
input_template = <<TEMPLATE
{
"containerOverrides": [
{
"name": "myproject-task",
"environment": [
{ "name": "S3_BUCKET", "value": <s3_bucket> },
{ "name": "S3_KEY", "value": <s3_key> }
]
}
]
}
TEMPLATE
}
}
If I remove the input_transformer section, it will work fine, but I need to pass in the s3 bucket and key to process the particular file.
My rationale for doing this is to remove the need for an intermediary Lambda and was guided by this Medium post: https://medium.com/#bowbaq/trigger-an-ecs-job-when-an-s3-upload-completes-3559c44c37d1
Any advice is appreciated.
After hours of going in circles, I found an answer!
So the first step is to check what the cause of the failed invocation is. You can do this by checking CloudTrail logs by navigating to Cloud Trail > Event history > Search by Event name and type RunTask in the search box. You should see a series of events from the event source ecs.amazonaws.com. Find one that relates to your the Failed Invocation you experienced.
When you click into the event, you can see under the Event record section an errorMessage. In my case, it was the following:
"errorCode": "InvalidParameterException",
"errorMessage": "Override for container named myproject-task is not a container in the TaskDefinition.",
This may be different for you. For me, it was because my containerOverride name was incorrect. This field refers to: The name of the container that receives the override. This parameter is required if any override is specified. ref: https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerOverride.html
Correcting this field fixed my issue.

Is there any solution for remove or hide top toolbar section in flexmonster with react-native?

I trying to hide/remove toolbar section( CSV, JSON, OLAP, etc) on my app, which is using react-native-flexmonster, as seen on the image below:
I tried this, but without success
Here is my code:
<FlexmonsterReactNative.Pivot
container= "pivot-container"
toolbar={false}
report = {{
dataSource: {
filename: "data/data.csv"
},
slice: {
columns: [{
uniqueName: "Color"
}],
rows: [{
uniqueName: "Country"
}, {
uniqueName: "[Measures]"
}],
measures: [{
uniqueName: "Price",
format: "currency"
}, {
uniqueName: "Discount",
format: "currency"
}],
},
formats: [{
name: "currency",
currencySymbol: "$",
currencySymbolAlign: "left",
thousandsSeparator: ",",
decimalPlaces: 2
}],
conditions: [{
formula: "#value < 2000",
measure: "Discount",
format: {
backgroundColor: "#CCFFCC",
}
}, {
formula: "AND(#value > 2000, #value < 4000)",
measure: "Discount",
format: {
backgroundColor: "#FFFF99",
}
}]
}}
/>
Some features provided by Flexmonster are not available in React Native while using their module due to some limitations it imposes on the execution of JavaScript.
It includes enabling/disabling the Toolbar.
Even so, it is possible to modify the module itself in the way the desired configuration is adjusted.
For example, the possibility to disable the Toolbar be achieved using the following approach:
Download the module mentioned earlier and modify the following code snippet in the way the toolbar property of the created instance is set to false: https://github.com/flexmonster/react-native-flexmonster/blob/f8d0f7fd6614c06e1a31585c8b8cbe22e3bc653e/src/index.js#L360-L371.
For example:
<script>
new Flexmonster({
container: "#pivot-container",
componentFolder: "<https://cdn.flexmonster.com/>",
toolbar: false,
height: ${height},
width: ${width},
report: JSON.parse('${JSON.stringify(this.props.report)}')
});
${this.registerEvents()}
</script>
Please note that in case such methods are required, the module should be downloaded and connected manually instead of installation through npm.