boto3 get_metric_statistics returning empty datapoints - python

I'm trying to make a simple python plugin that returns metrics on dynamodb but I can only get it to return an empty datapoint.
#!/usr/bin/env python
import sys
import boto3
import time
import optparse
from pprint import pprint
from datetime import datetime
from datetime import timedelta
def initialize_client():
client = boto3.client(
'cloudwatch',
aws_access_key_id = 'xxxxx',
aws_secret_access_key = 'xxxxx',
region_name = 'us-east-2'
)
return client
def request_metric(client):
response = client.get_metric_statistics(
Namespace = 'AWS/DynamoDB',
Period = 120,
StartTime = datetime.utcnow() - timedelta(days=2),
EndTime = datetime.utcnow(),
MetricName = 'ConsumedWriteCapacityUnits',
Statistics=['Average'],
Dimensions = [
{
'Name': 'TableName',
'Value': 'test'
}
],
)
return response
def main():
client = initialize_client()
response = request_metric(client)
pprint(response)
return 0
main()
Here is the output I get:
{u'Datapoints': [],
u'Label': 'ConsumedWriteCapacityUnits',
'ResponseMetadata': {'HTTPHeaders': {'content-length': '349',
'content-type': 'text/xml',
'date': 'Wed, 22 Aug 2018 20:57:44 GMT',
'x-amzn-requestid': 'xxxxx'},
'HTTPStatusCode': 200,
'RequestId': 'xxxxx',
'RetryAttempts': 0}}
I was able to get it working with RDS but I can't seem to get DynamoDB to return datapoints. What am I missing here?

There was an issue with the start time. Once I set
StartTime = datetime.utcnow() - timedelta(seconds = 600),
to 600 seconds instead of 2 days I was able to get datapoints. Also make sure the region is correct.

Related

RestAPI filter params JSON

I'm trying to get the last data from the bitmex API
Base URI: https://www.bitmex.com/api/v1
I don't really understand how to get the last data (from today) using filters : https://www.bitmex.com/app/restAPI
here is my code:
from datetime import date
import requests
import json
import pandas as pd
today = date.today()
d1 = today.strftime("%Y-%m-%d")
#print("d1 =", d1)
def parser():
today = date.today()
# yy/dd/mm
d1 = today.strftime("%Y-%m-%d")
# print("d1 =", d1)
return f'https://www.bitmex.com/api/v1/trade?symbol=.BVOL24H&startTime={d1}&timestamp.time=12:00:00.000&columns=price'
# Making a get request
response = requests.get(parser()).json()
# print(response)
for elem in response:
print(elem)
and the response is :
...
{'symbol': '.BVOL24H', 'timestamp': '2021-12-27T08:05:00.000Z', 'price': 2.02}
{'symbol': '.BVOL24H', 'timestamp': '2021-12-27T08:10:00.000Z', 'price': 2.02}
{'symbol': '.BVOL24H', 'timestamp': '2021-12-27T08:15:00.000Z', 'price': 2.02}
it's missing a few hours, I tried using endTime, StartTime and Count without success..
I think I need to pass another filter like endtime = now and timestamp.time = now but I don't know how to send a payload or how to url-encode it.
As Filtering part tells
Many table endpoints take a filter parameter. This is expected to be JSON
These parameters are not keys in the query string, but keys in a dictionary given in filter key
url = "https://www.bitmex.com/api/v1/trade"
filters = {
'startTime': date(2021, 12, 20).strftime("%Y-%m-%d"),
'timestamp.time': '12:00:00.000'
}
params = {
'symbol': '.BVOL24H',
'filter': json.dumps(filters),
}
response = requests.get(url, params=params)
for elem in response.json():
print(elem)
Example
/trade?symbol=.BVOL24H&filter={%22startTime%22:%222021-12-20%22,%22timestamp.time%22:%2212:00:00.000%22}
You can add additional parameters to the url with & like below.
'https://www.bitmex.com/api/v1/trade?symbol=.BVOL24H&startTime={d1}&timestamp.time=12:00:00.000&columns=price&endTime={date.today()}&timestamp.time={date.today()}'

Flashbots "X-Flashbots-Signature" header not working correctly with web3.py

Recently I've been having some trouble with the X-Flashbots-Signature header when sending a request to the flashbots goerli endpoint.
My python code looks like this:
import requests
import json
import secrets
from eth_account import Account, messages
from web3 import Web3
from math import ceil
rpcUrl = GOERLI_RPC_NODE_PROVIDER
web3 = Web3(Web3.HTTPProvider(rpcUrl))
publicKey = ETH_PUBLIC_KEY
privateKey = ETH_PRIVATE_KEY
contractAddress = GOERLI_TEST_CONTRACT # Goerli test contract
data = CONTRACT_DATA # Contract data to execute
signed = []
for _ in range(2):
nonce = web3.eth.getTransactionCount(publicKey, 'pending')
checksumAddress = Web3.toChecksumAddress(contractAddress)
checksumPublic = Web3.toChecksumAddress(publicKey)
tx = {
'nonce': nonce,
'to': checksumAddress,
'from': checksumPublic,
'value': 0,
'gasPrice': web3.toWei(200, 'gwei'),
'data': data
}
gas = web3.eth.estimateGas(tx)
tx['gas'] = ceil(gas + gas * .1)
signed_tx = web3.eth.account.signTransaction(tx, privateKey)
signed.append(Web3.toHex(signed_tx.rawTransaction))
dt = {
'jsonrpc': '2.0',
'method': 'eth_sendBundle',
'params': [
{
'txs': [
signed[0], signed[1] # Signed txs with web3.eth.account.signTransaction
],
'blockNumber': web3.eth.block_number + 1,
'minTimestamp': '0x0',
'maxTimestamp': '0x0',
'revertingTxHashes': []
}
],
'id': 1337
}
pvk = secrets.token_hex(32)
pbk = Account.from_key(pvk).address
body = json.dumps(dt)
message = messages.encode_defunct(text=Web3.keccak(text=body).hex())
signature = pbk + ':' + Account.sign_message(message, pvk).signature.hex()
hd = {
'Content-Type': 'application/json',
'X-Flashbots-Signature': signature,
}
res = requests.post('https://relay-goerli.flashbots.net/', headers=hd, data=body)
print(res.text)
This code is a modified version of code taken straight from the flashbots docs: https://docs.flashbots.net/flashbots-auction/searchers/advanced/rpc-endpoint/#authentication
Upon running this code I get an internal server error error response. At first, I thought the problem might be fixed by replacing text=Web3.keccak(text=body).hex() to hexstr=Web3.keccak(text=body).hex() or primative=Web3.keccak(text=body), as per the definition of messages.encode_defunct: https://eth-account.readthedocs.io/en/stable/eth_account.html#eth_account.messages.encode_defunct. But after making this replacement, I got the error signer address does not equal expected. This is very confusing, especially because I have resolved the message
with the signature myself and the public key does match. But whenever I send it to the flashbots endpoint, I am left with this error.
Any ideas would be greatly appreciated.

FTX API to create order

It show error {"success":false,"error":"Missing parameter market"}
import time
import hmac
from requests import Request
import requests
import json
api_key=''
api_secret=''
payload = json.dumps({
"market": 'XRP/USDT',
"side": 'BUY',
"price": 0.7,
"size": 1,
"type": "limit",
"reduceOnly": False,
"ioc": False,
"postOnly": False,
"clientId": None
})
ts = int(time.time() * 1000)
request = Request('POST', 'https://ftx.com/api/orders')
prepared = request.prepare()
signature_payload = f'{ts}{prepared.method}{prepared.path_url}{payload}'.encode()
print(signature_payload)
signature = hmac.new(api_secret.encode(), signature_payload, 'sha256').hexdigest()
prepared.headers['FTX-KEY'] = api_key
prepared.headers['FTX-SIGN'] = signature
prepared.headers['FTX-TS'] = str(ts)
url='https://ftx.com/api/orders'
response = requests.request("POST", url,headers=prepared.headers,data=payload)
print(response.text)
Can you please recommend how to fix ? I have try many way but it doesn't work
You may try
prepared.headers['Content-Type'] = 'application/json'
Hello I know this question is a bit older, but maybe someone else needs an answer.
I sent prepared and it worked for me.
from requests import Request, Session
import hmac
import json
import time
from pprint import pprint
API_KEY = ""
API_SECRET = ""
SUBACCOUNT = ""
def place_order(market, side, price, size, order_type, reduceOnly, postOnly, ioc=False):
endpoint = "https://ftx.com/api/orders"
ts = int(time.time() * 1000)
s = Session()
data = json.dumps({
"market": market,
"side": side,
"price": price,
"type": order_type,
"size": size,
"reduceOnly": reduceOnly,
"ioc": ioc,
"postOnly": postOnly
})
request = Request("POST", endpoint, data=data)
prepared = request.prepare()
signature_payload = f"{ts}{prepared.method}{prepared.path_url}{data}".encode()
signature = hmac.new(API_SECRET.encode(), signature_payload, "sha256").hexdigest()
prepared.headers["FTX-KEY"] = API_KEY
prepared.headers["FTX-SIGN"] = signature
prepared.headers["FTX-TS"] = str(ts)
prepared.headers["FTX-SUBACCOUNT"] = SUBACCOUNT
response = s.send(prepared)
data = response.json()
pprint(data)
return data

Runtime.MarshalError in python

I am Getting this error. I am executing code of aws lambda function using python 3.7 to know quicksight dashboard version. Thanks in advance!
errorMessage: "Unable to marshal response: Object of type datetime is not JSON serializable",
errorType : "Runtime.MarshalError"
Code-
import boto3
import time
import sys
client = boto3.client('quicksight')
def lambda_handler(event, context):
response = client.list_dashboard_versions(AwsAccountId='11111', DashboardId='2222',MaxResults=10)
return response
I quick fix could be:
import boto3
import time
import sys
import json
client = boto3.client('quicksight')
def lambda_handler(event, context):
response = client.list_dashboard_versions(AwsAccountId='11111', DashboardId='2222',MaxResults=10)
return json.dumps(response, default=str)
Looking at https://boto3.amazonaws.com/v1/documentation/api/1.14.8/reference/services/quicksight.html#QuickSight.Client.list_dashboard_versions the return looks like this -
{
'DashboardVersionSummaryList': [
{
'Arn': 'string',
'CreatedTime': datetime(2015, 1, 1),
'VersionNumber': 123,
'Status': 'CREATION_IN_PROGRESS'|'CREATION_SUCCESSFUL'|'CREATION_FAILED'|'UPDATE_IN_PROGRESS'|'UPDATE_SUCCESSFUL'|'UPDATE_FAILED',
'SourceEntityArn': 'string',
'Description': 'string'
},
],
'NextToken': 'string',
'Status': 123,
'RequestId': 'string'
}
As you can see, CreatedTime is returned as datetime. If you want to return this as a JSON, you should transform this value.
I was struggling with this today with a method that also returns a datetime.
In my example 'JoinedTimestamp': datetime(2015, 1, 1) resulting in the same Unable to marshal response.
If you don't need the CreatedTime value you might as well remove it from the response as:
for account in list_accounts_response["Accounts"]:
if "JoinedTimestamp" in account:
del account["JoinedTimestamp"]
To follow up on Joseph Lane's answer, transforming this value could be something along the lines of:
for account in list_accounts_response["Accounts"]:
if "JoinedTimestamp" in account:
account["JoinedTimestamp"] = str(account["JoinedTimestamp"])

boto3 request_spot_instances method does not work with "UserData"

I'm trying to make AWS EC2 spot instance request via AWS Lambda, and using boto3 to make call to EC2 API.
Now I can create spot instance, but "UserData" param is not working.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import boto3
import json
import logging
import base64
import os
from pathlib import Path
def request_spot_instance(access_key, secret_key):
ec2_client = boto3.client('ec2',
aws_access_key_id = access_key,
aws_secret_access_key = secret_key,
region_name = 'ap-northeast-1'
)
response = ec2_client.request_spot_instances(
SpotPrice = '0.2',
Type = 'one-time',
LaunchSpecification = {
'ImageId': 'ami-be4a24d9',
'KeyName': 'my_key',
'InstanceType':'c4.large',
'UserData': base64.encodestring(u'#!/bin/sh \n touch foo.txt'.encode('utf-8')).decode('ascii'),
'Placement':{},
'SecurityGroupIds':[
'sg-6bd2780c'
]
}
)
return response
def lambda_handler(event, context):
response = request_spot_instance(os.environ.get('AWS_ACCESS_KEY_ID'), os.environ.get('AWS_SECRET_ACCESS_KEY'))
print(response)
return event, context
if __name__ == "__main__":
lambda_handler("","")
I'm using this code with Python 2.7.11.
The response of request method is:
{u'SpotInstanceRequests': [{u'Status': {u'UpdateTime': datetime.datetime(2016, 12, 23, 6, 11, 8, tzinfo=tzutc()), u'Code': 'pending-evaluation', u'Message': 'Your Spot request has been submitted for review, and is pending evaluation.'}, u'ProductDescription': 'Linux/UNIX', u'SpotInstanceRequestId': 'sir-cerib8cg', u'State': 'open', u'LaunchSpecification': {u'Placement': {u'AvailabilityZone': 'ap-northeast-1c'}, u'ImageId': 'ami-be4a24d9', u'KeyName': 'miz_private_key', u'SecurityGroups': [{u'GroupName': 'ssh only', u'GroupId': 'sg-6bd2780c'}], u'SubnetId': 'subnet-32c6626a', u'Monitoring': {u'Enabled': False}, u'InstanceType': 'c4.large'}, u'Type': 'one-time', u'CreateTime': datetime.datetime(2016, 12, 23, 6, 11, 8, tzinfo=tzutc()), u'SpotPrice': '0.200000'}], 'ResponseMetadata': {'RetryAttempts': 0, 'HTTPStatusCode': 200, 'RequestId': '285867eb-9303-4a6d-83fa-5ccfdadd482f', 'HTTPHeaders': {'transfer-encoding': 'chunked', 'vary': 'Accept-Encoding', 'server': 'AmazonEC2', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Fri, 23 Dec 2016 06:11:08 GMT'}}}
This response does not not include "UserData", which seems differ from wrote in boto3 manual.
I'm suspecting UserData param is not accepted.
Any suggestions are welcome.
Self resolved.
The user data shell script was executed at root "/" directory, and simply I could not find the generated file.
$ ls -al /foo.txt
-rw-r--r-- 1 root root 0 Dec 23 07:03 /foo.txt

Categories

Resources