Which class in AWS CDK have option to configure Dynamic partitioning for Kinesis delivery stream - amazon-s3

I'm using kinesis delivery stream to send stream, from event bridge to s3 bucket. But i can't seem to find which class have the option to configure dynamic partitioning?
this is my code for delivery stream:
new CfnDeliveryStream(this, `Export-delivery-stream`, {
s3DestinationConfiguration: {
bucketArn: bucket.bucketArn,
roleArn: kinesisFirehoseRole.roleArn,
prefix: `test/!{timestamp:yyyy/MM/dd}/`
}
});

I have been working on the same issue for a few days, and have finally gotten something to work. Here is an example of how it can be implemented in CDK. In short, the partitioning has to be enables as you have done, but you need to set the key and .jq expression in the so-called processingConfiguration.
Our incomming json data looks something like this:
{
"data":
{
"timestamp":1633521266990,
"defaultTopic":"Topic",
"data":
{
"OUT1":"Inactive",
"Current_mA":3.92
}
}
}
The CDK code looks as following:
const DeliveryStream = new CfnDeliveryStream(this, 'deliverystream', {
deliveryStreamName: 'deliverystream',
extendedS3DestinationConfiguration: {
cloudWatchLoggingOptions: {
enabled: true,
},
bucketArn: Bucket.bucketArn,
roleArn: deliveryStreamRole.roleArn,
prefix: 'defaultTopic=!{partitionKeyFromQuery:defaultTopic}/!{timestamp:yyyy/MM/dd}/',
errorOutputPrefix: 'error/!{firehose:error-output-type}/',
bufferingHints: {
intervalInSeconds: 60,
},
dynamicPartitioningConfiguration: {
enabled: true,
},
processingConfiguration: {
enabled: true,
processors: [
{
type: 'MetadataExtraction',
parameters: [
{
parameterName: 'MetadataExtractionQuery',
parameterValue: '{defaultTopic: .data.defaultTopic}',
},
{
parameterName: 'JsonParsingEngine',
parameterValue: 'JQ-1.6',
},
],
},
{
type: 'AppendDelimiterToRecord',
parameters: [
{
parameterName: 'Delimiter',
parameterValue: '\\n',
},
],
},
],
},
},
})

Related

RabbitMQ/Krakend/NestJS - How can I post the consumed message through Krakend API's async agent?

This is my config for krakend.json
"async_agent": [
{
"name": "test-agent",
"connection": {
"max_retries": 10,
"backoff_strategy": "exponential-jitter"
},
"consumer": {
"topic": "krakend",
"workers": 5
},
"backend": [
{
"url_pattern": "/greeted",
"method": "POST",
"host": [ "http://127.0.0.1:2999" ],
"disable_host_sanitize": false
}
],
"extra_config": {
"async/amqp": {
"host": "amqp://guest:guest#localhost:5672/",
"name": "krakend",
"exchange": "ApiGatewayExchange",
"durable": true,
"delete": false,
"exclusive": false,
"no_wait": false,
"auto_ack": false
}
}
}
]
Messages are sent from service-a like so:
export class AppService {
constructor(#Inject('GREETING_SERVICE') private client: ClientProxy){}
getHello(): ResponseDTO {
const responseDTO: ResponseDTO = {
action: 'Hello',
service: 'from service A'
}
this.client.emit('', responseDTO);
return responseDTO;
}
}
And imported GREETING_SERVICE config like so:
imports: [
ClientsModule.register([
{
name: 'GREETING_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://test:test#localhost:5672/'],
queue: 'krakend'
}
}
])
],
Lastly, this is the endpoint in another service (let's call this service-c) that gets that message from the consumer:
#Post('greeted')
TestHello(#Body() data: any) {
console.log(data)
return data
}
The message is successfully consumed as set by the async_agent in my krakend file, but the message isn't posted as a body to that endpoint. When I did a console.log of that data supposedly passed, it just prints {}.
Am I doing anything wrong here? Been scratching my head for hours.
The async part of your krakend.json configuration looks good to me, but I am suspecting about the problem you might have.
Most of the javascript frameworks today will require you to pass specific headers to work their magic like Content-Type or Accept. You have to take into account that KrakenD will pass a very reduced set of headers to your NestJS application (Accept-Encoding and User-Agent as far as I can remember).
I am unfamiliar with NestJS, but I would bet that you need to pass the Content-Type and you are good to go. Here's my suggestion of configuration:
"async_agent": [
{
"name": "test-agent",
"connection": {
"max_retries": 10,
"backoff_strategy": "exponential-jitter"
},
"consumer": {
"topic": "krakend",
"workers": 5
},
"backend": [
{
"url_pattern": "/greeted",
"method": "POST",
"host": [
"http://127.0.0.1:2999"
],
"disable_host_sanitize": false,
"extra_config": {
"modifier/martian": {
"header.Modifier": {
"scope": [
"request"
],
"name": "Content-Type",
"value": "application/json"
}
}
}
}
],
"extra_config": {
"async/amqp": {
"host": "amqp://guest:guest#localhost:5672/",
"name": "krakend",
"exchange": "ApiGatewayExchange",
"durable": true,
"delete": false,
"exclusive": false,
"no_wait": false,
"auto_ack": false
}
}
}
]
}
Hope this helps

Kafka Connect: How to extract a field

I'm using Debezium SQL Server Connector to stream a table into a topic. Thanks to Debezium's ExtractNewRecordState SMT, I'm getting the following message in my topic.
{
"schema":{
"type":"struct",
"fields":[
{
"type":"int64",
"optional":false,
"field":"id"
},
{
"type":"string",
"optional":false,
"field":"customer_code"
},
{
"type":"string",
"optional":false,
"field":"topic_name"
},
{
"type":"string",
"optional":true,
"field":"payload_key"
},
{
"type":"boolean",
"optional":false,
"field":"is_ordered"
},
{
"type":"string",
"optional":true,
"field":"headers"
},
{
"type":"string",
"optional":false,
"field":"payload"
},
{
"type":"int64",
"optional":false,
"name":"io.debezium.time.Timestamp",
"version":1,
"field":"created_on"
}
],
"optional":false,
"name":"test_server.dbo.kafka_event.Value"
},
"payload":{
"id":129,
"customer_code":"DVTPRDFT411",
"topic_name":"DVTPRDFT411",
"payload_key":null,
"is_ordered":false,
"headers":"{\"kafka_timestamp\":1594566354199}",
"payload":"MSG 18",
"created_on":1594595154267
}
}
After adding value.converter.schemas.enable=false, I could get rid of the schema portion and only the payload part is left as shown below.
{
"id":130,
"customer_code":"DVTPRDFT411",
"topic_name":"DVTPRDFT411",
"payload_key":null,
"is_ordered":false,
"headers":"{\"kafka_timestamp\":1594566354199}",
"payload":"MSG 19",
"created_on":1594595154280
}
I'd like to go 1 step further and extract only the customer_code field. I tried ExtractField$Value SMT but I keep getting the exception IllegalArgumentException: Unknown field: customer_code.
My configuration is as following
transforms=unwrap,extract
transforms.unwrap.type=io.debezium.transforms.ExtractNewRecordState
transforms.unwrap.drop.tombstones=true
transforms.unwrap.delete.handling.mode=drop
transforms.extract.type=org.apache.kafka.connect.transforms.ExtractField$Key
transforms.extract.field=customer_code
I tried a bunch of other SMTs including ExtractField$Key, ValueToKey but I couldn't make it work. I'd be very grateful if you could show me what I've done wrong. According to this tutorial from Confluent, it should work but it didn't.
** UPDATE **
I'm running Kafka Connect using connect-standalone worker.properties sqlserver.properties.
worker.properties
offset.storage.file.filename=C:/development/kafka_2.12-2.5.0/data/kafka/connect/connect.offsets
plugin.path=C:/development/kafka_2.12-2.5.0/plugins
bootstrap.servers=127.0.0.1:9092
offset.flush.interval.ms=10000
rest.port=10082
rest.host.name=127.0.0.1
rest.advertised.port=10082
rest.advertised.host.name=127.0.0.1
internal.key.converter=org.apache.kafka.connect.json.JsonConverter
internal.value.converter=org.apache.kafka.connect.json.JsonConverter
internal.key.converter.schemas.enable=false
internal.value.converter.schemas.enable=false
key.converter=org.apache.kafka.connect.json.JsonConverter
value.converter=org.apache.kafka.connect.json.JsonConverter
value.converter.schemas.enable=false
sqlserver.properties
name=sql-server-connector
connector.class=io.debezium.connector.sqlserver.SqlServerConnector
database.hostname=127.0.0.1
database.port=1433
database.user=sa
database.password=dummypassword
database.dbname=STGCTR
database.history.kafka.bootstrap.servers=127.0.0.1:9092
database.server.name=wfo
table.whitelist=dbo.kafka_event
database.history.kafka.topic=db_schema_history
transforms=unwrap,extract
transforms.unwrap.type=io.debezium.transforms.ExtractNewRecordState
transforms.unwrap.drop.tombstones=true
transforms.unwrap.delete.handling.mode=drop
transforms.extract.type=org.apache.kafka.connect.transforms.ExtractField$Value
transforms.extract.field=customer_code
The schema and payload fields sound like you're using data that was serialized with a JsonConverter with schemas enabled.
You can just set value.converter.schemas.enable=false to achieve your goal.

How to find the "Local Identifier" to execute AFM function using gooddata-js

I'm using gooddata-js in my project and I'm trying to use the function execution.executeAfm, but appears error about "Local identifier no found in AFM".
I followed the documentation about AFM and Result Specification, but I don't know where I find the "Local identifier" to put into itemIdentifiers. I tried put ['measureGroup'] but didn't work!
execution: {
afm: {
measures: [
// Type: IMeasure
{
localIdentifier: '740953a40a01490c8aaeba66a21cac53',
// Type: MeasureDefinition
definition: {
measure: {
// Type: ObjQualifier
item: {
uri: '/gdc/md/PROJECT_ID/obj/245828'
},
filters: [
// Type: IAbsoluteDateFilter
{
relativeDateFilter: {
dataSet: {
uri: '/gdc/md/PROJECT_ID/obj/3603'
},
from : 0,
granularity : 'GDC.time.month',
to : 0
}
},
],
computeRatio: false
}
},
}
]
},
resultSpec:
{
dimensions: [
{
itemIdentifiers: ['gdc.visualization.table']
}
]
}
}
I expect result of AFM function but show the error below!
error: {errorClass: "com.gooddata.webapp.service.executeafm.exception.LocalIdentifierNotFoundException",…}
component: "Webapp"
errorClass: "com.gooddata.webapp.service.executeafm.exception.LocalIdentifierNotFoundException"
errorCode: "gdc111"
errorId: "fe33be5e-cf0f-4195-b8eb-f28acafd8890"
message: "Local identifier=%s of type=%s not found in AFM."
parameters: ["gdc.visualization.table", "AttributeItem"]
0: "gdc.visualization.table"
1: "AttributeItem"
trace: ""
You are looking for a documentation of resultSpec available here:
https://sdk.gooddata.com/gooddata-ui/docs/result_specification.html
From your code snippet, I can only guess that a valid resultSpec could look something like this:
{
"dimensions": [
{
"itemIdentifiers": [
"measureGroup"
]
},
{
"itemIdentifiers": []
}
],
"sorts": []
}

Using rally app lookback API - unable to fetch defects that are tagged

I am using rally lookback API and creating a defect trend chart. I need to filter defects that do not have a tag "xyz".
Using the following:
this.myTrendChart = Ext.create('Rally.ui.chart.Chart', {
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: {
find: {
_TypeHierarchy: "Defect",
State: { $lt: "Closed"},
Tags.Name: { $nin: ["xyz"] },
_ProjectHierarchy: projectOid,
_ValidFrom: {$gte: startDateUTC}
}
},
calculatorType: 'Calci',
calculatorConfig: {},
chartConfig: {
chart: {
zoomType: 'x',
type: 'line'
},
title: {
text: 'Defect trend'
},
xAxis: {
type: 'datetime',
minTickInterval: 7
},
yAxis: {
title: {
text: 'Number of Defects'
}
}
}
});
This does not return any data. Need help with the filter for tags.
Tags is a collection of tag-oids so you'll need to find and use the oid of the tag vs the name, at which point it'll just be Tags: { $nin: [oid] }. Caveat: technically, due to how expensive it is, $nin is unsupported (https://rally1.rallydev.com/analytics/doc/#/manual/48e0589f681160fc316a8a4802dc389f)...but it doesn't throw an error so maybe it works anyway.

ExtJS4 - Load Store From Another Grid

I am trying to load a json store when I click on a particular row in another grid. Can anyone see what I am doing wrong here? In the ext-all.js the error comes back as data is undefined (from debugger).
Ext.define('Documents', {
extend: 'Ext.data.Model',
fields: [
{ name: 'index', type: 'int' },
{ name: 'path', type: 'string' }
]
});
var documents = new Ext.data.JsonStore({
model: 'Documents',
root: 'groupdocuments',
autoLoad: false
});
// in the Ext.grid.Panel
listeners: {
itemclick: function () {
var itemgroupid = rec.get('groupid');
Ext.Ajax.request({
url: '/GetDocuments',
params: { groupId: itemgroupid },
success: function (result) {
var jsondata = Ext.decode(result.responseText);
documents.loadData(jsondata);
}
});
}
}
// the sample json returned from url
// { "groupdocuments": [{ "index": 1, "path": "1.doc" }, { "index": 2, "path": "2.doc" }, { "index": 3, "path": "3.doc" }] }
it looks like you need to escape the path data. should be { path: "C:\\something\\" }
Also why not use the grid Grouping feature?
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.feature.Grouping
In looking further it looks like the loaddata function is expecting an array. Not a json object with a rootdata object like you are giving it. change the listener to the following:
var jsondata = Ext.decode(result.responseText);
documents.loadData(jsondata.groupdocuments);
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Store-method-loadData
alternatively you should be able to use loadRawData with the full json object.
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Store-method-loadRawData