diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 000000000..085e15544 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,51 @@ +FROM golang:1.13-alpine AS build + +RUN apk add --no-cache git openssh openssl-dev pkgconf gcc g++ make libc-dev bash + +WORKDIR /root + +COPY go.mod . +COPY go.sum . + +RUN go mod download + +COPY . . + +ARG SERVICE_NAME + +RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o service -tags musl openreplay/backend/services/$SERVICE_NAME + +FROM alpine +RUN apk add --no-cache ca-certificates + +ENV TZ=UTC \ + FS_ULIMIT=1000 \ + FS_DIR=/mnt/efs \ + MAXMINDDB_FILE=/root/geoip.mmdb \ + UAPARSER_FILE=/root/regexes.yaml \ + HTTP_PORT=80 \ + KAFKA_USE_SSL=true \ + REDIS_STREAMS_MAX_LEN=3000 \ + TOPIC_RAW=raw \ + TOPIC_CACHE=cache \ + TOPIC_ANALYTICS=analytics \ + TOPIC_TRIGGER=trigger \ + TOPIC_EVENTS=events \ + GROUP_SINK=sink \ + GROUP_STORAGE=storage \ + GROUP_DB=db \ + GROUP_ENDER=ender \ + GROUP_CACHE=cache \ + AWS_REGION_WEB=eu-central-1 \ + AWS_REGION_IOS=eu-west-1 \ + AWS_REGION_ASSETS=eu-central-1 \ + + +ARG SERVICE_NAME +RUN if [ "$SERVICE_NAME" = "http" ]; then \ + wget https://raw.githubusercontent.com/ua-parser/uap-core/master/regexes.yaml -O "$UAPARSER_FILE" &&\ + wget https://static.openreplay.com/geoip/GeoLite2-Country.mmdb -O "$MAXMINDDB_FILE"; fi + + +COPY --from=build /root/service /root/service +ENTRYPOINT /root/service diff --git a/backend/build.sh b/backend/build.sh new file mode 100644 index 000000000..3b3014282 --- /dev/null +++ b/backend/build.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Script to build api module +# flags to accept: +# ee: build for enterprize edition. +# Default will be OSS build. + +# Example +# DOCKER_REPO=asayer.io bash buid.sh + +git_sha1=$(git rev-parse HEAD) +ee="false" +check_prereq() { + which docker || { + echo "Docker not installed, please install docker." + exit=1 + } + [[ exit -eq 1 ]] && exit 1 +} + +function build_api(){ + # Copy enterprize code + [[ $1 == "ee" ]] && { + cp ../ee/backend/* ./ + ee="true" + } + [[ $2 != "" ]] && { + image="$2" + docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --build-arg SERVICE_NAME=$image . + return + } + for image in $(ls services); + do + docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --build-arg SERVICE_NAME=$image . + echo "::set-output name=image::${DOCKER_REPO:-'local'}/$image:${git_sha1}" + done +} + +check_prereq +build_api $1 $2 diff --git a/backend/go.mod b/backend/go.mod new file mode 100644 index 000000000..2729bcccc --- /dev/null +++ b/backend/go.mod @@ -0,0 +1,21 @@ +module openreplay/backend + +go 1.13 + +require ( + github.com/btcsuite/btcutil v1.0.2 + github.com/confluentinc/confluent-kafka-go v1.5.2 // indirect + github.com/go-redis/redis v6.15.9+incompatible + github.com/google/uuid v1.1.1 + github.com/jackc/pgconn v1.6.0 + github.com/jackc/pgx/v4 v4.6.0 + github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451 + github.com/klauspost/compress v1.11.9 + github.com/klauspost/pgzip v1.2.5 + github.com/oschwald/maxminddb-golang v1.7.0 + github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce + github.com/ua-parser/uap-go v0.0.0-20200325213135-e1c09f13e2fe + gopkg.in/confluentinc/confluent-kafka-go.v1 v1.5.2 + github.com/ClickHouse/clickhouse-go v1.4.3 + github.com/aws/aws-sdk-go v1.35.23 +) diff --git a/backend/go.sum b/backend/go.sum new file mode 100644 index 000000000..8e7453a17 --- /dev/null +++ b/backend/go.sum @@ -0,0 +1,161 @@ +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/confluentinc/confluent-kafka-go v1.4.2 h1:13EK9RTujF7lVkvHQ5Hbu6bM+Yfrq8L0MkJNnjHSd4Q= +github.com/confluentinc/confluent-kafka-go v1.4.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.6.0 h1:8FiBxMxS/Z0eQ9BeE1HhL6pzPL1R5x+ZuQ+T86WgZ4I= +github.com/jackc/pgconn v1.6.0/go.mod h1:yeseQo4xhQbgyJs2c87RAXOH2i624N0Fh1KSPJya7qo= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY= +github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 h1:Q3tB+ExeflWUW7AFcAhXqk40s9mnNYLk1nOkKNZ5GnU= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.3.0 h1:l8JvKrby3RI7Kg3bYEeU9TA4vqC38QDpFCfcrC7KuN0= +github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik= +github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= +github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.6.0 h1:Fh0O9GdlG4gYpjpwOqjdEodJUQM9jzN3Hdv7PN0xmm0= +github.com/jackc/pgx/v4 v4.6.0/go.mod h1:vPh43ZzxijXUVJ+t/EmXBtFmbFVO72cuneCT9oAlxAg= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/oschwald/maxminddb-golang v1.7.0 h1:JmU4Q1WBv5Q+2KZy5xJI+98aUwTIrPPxZUkd5Cwr8Zc= +github.com/oschwald/maxminddb-golang v1.7.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= +github.com/ua-parser/uap-go v0.0.0-20200325213135-e1c09f13e2fe h1:aj/vX5epIlQQBEocKoM9nSAiNpakdQzElc8SaRFPu+I= +github.com/ua-parser/uap-go v0.0.0-20200325213135-e1c09f13e2fe/go.mod h1:OBcG9bn7sHtXgarhUEb3OfCnNsgtGnkVf41ilSZ3K3E= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191224085550-c709ea063b76 h1:Dho5nD6R3PcW2SH1or8vS0dszDaXRxIw55lBX7XiE5g= +golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/confluentinc/confluent-kafka-go.v1 v1.4.2 h1:JabkIV98VYFqYKHHzXtgGMFuRgFBNTNzBytbGByzrJI= +gopkg.in/confluentinc/confluent-kafka-go.v1 v1.4.2/go.mod h1:ZdI3yfYmdNSLQPNCpO1y00EHyWaHG5EnQEyL/ntAegY= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/backend/pkg/db/cache/messages_common.go b/backend/pkg/db/cache/messages_common.go new file mode 100644 index 000000000..0b7d9a885 --- /dev/null +++ b/backend/pkg/db/cache/messages_common.go @@ -0,0 +1,30 @@ +package cache + +import ( + . "openreplay/backend/pkg/messages" +// . "openreplay/backend/pkg/db/types" +) + +func (c *PGCache) insertSessionEnd(sessionID uint64, timestamp uint64 ) error { + //duration, err := c.Conn.InsertSessionEnd(sessionID, timestamp) + _, err := c.Conn.InsertSessionEnd(sessionID, timestamp) + if err != nil { + return err + } + c.DeleteSession(sessionID) + // session, err := c.GetSession(sessionID) + // if err != nil { + // return err + // } + // session.Duration = &duration + return nil +} + + +func (c *PGCache) InsertIssueEvent(sessionID uint64, crash *IssueEvent) error { + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + return c.Conn.InsertIssueEvent(sessionID, session.ProjectID, crash) +} diff --git a/backend/pkg/db/cache/messages_ios.go b/backend/pkg/db/cache/messages_ios.go new file mode 100644 index 000000000..151ffe58e --- /dev/null +++ b/backend/pkg/db/cache/messages_ios.go @@ -0,0 +1,140 @@ +package cache + +import ( + "errors" + . "openreplay/backend/pkg/messages" + . "openreplay/backend/pkg/db/types" +) + +func (c *PGCache) InsertIOSSessionStart(sessionID uint64, s *IOSSessionStart) error { + if c.sessions[ sessionID ] != nil { + return errors.New("This session already in cache!") + } + c.sessions[ sessionID ] = &Session{ + SessionID: sessionID, + Platform: "ios", + Timestamp: s.Timestamp, + ProjectID: uint32(s.ProjectID), + TrackerVersion: s.TrackerVersion, + RevID: s.RevID, + UserUUID: s.UserUUID, + UserOS: s.UserOS, + UserOSVersion: s.UserOSVersion, + UserDevice: s.UserDevice, + UserCountry: s.UserCountry, + } + if err := c.Conn.InsertSessionStart(sessionID, c.sessions[ sessionID ]); err != nil { + c.sessions[ sessionID ] = nil + return err + } + return nil; +} + +func (c *PGCache) InsertIOSSessionEnd(sessionID uint64, e *IOSSessionEnd) error { + return c.insertSessionEnd(sessionID, e.Timestamp) +} + + +func (c *PGCache) InsertIOSScreenEnter(sessionID uint64, screenEnter *IOSScreenEnter) error { + if err := c.Conn.InsertIOSScreenEnter(sessionID, screenEnter); err != nil { + return err + } + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + session.PagesCount += 1 + return nil +} + +func (c *PGCache) InsertIOSClickEvent(sessionID uint64, clickEvent *IOSClickEvent) error { + if err := c.Conn.InsertIOSClickEvent(sessionID, clickEvent); err != nil { + return err + } + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + session.EventsCount += 1 + return nil +} + +func (c *PGCache) InsertIOSInputEvent(sessionID uint64, inputEvent *IOSInputEvent) error { + if err := c.Conn.InsertIOSInputEvent(sessionID, inputEvent); err != nil { + return err + } + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + session.EventsCount += 1 + return nil +} + +func (c *PGCache) InsertIOSCrash(sessionID uint64, crash *IOSCrash) error { + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + if err := c.Conn.InsertIOSCrash(sessionID, session.ProjectID, crash); err != nil { + return err + } + session.ErrorsCount += 1 + return nil +} + +func (c *PGCache) InsertIOSIssueEvent(sessionID uint64, issueEvent *IOSIssueEvent) error { + // session, err := c.GetSession(sessionID) + // if err != nil { + // return err + // } + // TODO: unite IssueEvent message for the all platforms + // if err := c.Conn.InsertIssueEvent(sessionID, session.ProjectID, issueEvent); err != nil { + // return err + // } + return nil +} + +func (c *PGCache) InsertUserID(sessionID uint64, userID *IOSUserID) error { + if err := c.Conn.InsertIOSUserID(sessionID, userID); err != nil { + return err + } + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + session.UserID = &userID.Value + return nil +} + +func (c *PGCache) InsertUserAnonymousID(sessionID uint64, userAnonymousID *IOSUserAnonymousID) error { + if err := c.Conn.InsertIOSUserAnonymousID(sessionID, userAnonymousID); err != nil { + return err + } + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + session.UserAnonymousID = &userAnonymousID.Value + return nil +} + +func (c *PGCache) InsertMetadata(sessionID uint64, metadata *Metadata) error { + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + project, err := c.GetProject(session.ProjectID) + if err != nil { + return err + } + + keyNo := project.GetMetadataNo(metadata.Key) + if err := c.Conn.InsertMetadata(sessionID, keyNo, metadata.Value); err != nil { + return err + } + + session.SetMetadata(keyNo, metadata.Value) + return nil +} + diff --git a/backend/pkg/db/cache/messages_web.go b/backend/pkg/db/cache/messages_web.go new file mode 100644 index 000000000..3afae8592 --- /dev/null +++ b/backend/pkg/db/cache/messages_web.go @@ -0,0 +1,56 @@ +package cache + +import ( + "errors" + . "openreplay/backend/pkg/messages" + . "openreplay/backend/pkg/db/types" +) + + +func (c *PGCache) InsertWebSessionStart(sessionID uint64, s *SessionStart) error { + if c.sessions[ sessionID ] != nil { + return errors.New("This session already in cache!") + } + c.sessions[ sessionID ] = &Session{ + SessionID: sessionID, + Platform: "web", + Timestamp: s.Timestamp, + ProjectID: uint32(s.ProjectID), + TrackerVersion: s.TrackerVersion, + RevID: s.RevID, + UserUUID: s.UserUUID, + UserOS: s.UserOS, + UserOSVersion: s.UserOSVersion, + UserDevice: s.UserDevice, + UserCountry: s.UserCountry, + // web properties (TODO: unite different platform types) + UserAgent: s.UserAgent, + UserBrowser: s.UserBrowser, + UserBrowserVersion: s.UserBrowserVersion, + UserDeviceType: s.UserDeviceType, + UserDeviceMemorySize: s.UserDeviceMemorySize, + UserDeviceHeapSize: s.UserDeviceHeapSize, + } + if err := c.Conn.InsertSessionStart(sessionID, c.sessions[ sessionID ]); err != nil { + c.sessions[ sessionID ] = nil + return err + } + return nil; +} + +func (c *PGCache) InsertWebSessionEnd(sessionID uint64, e *SessionEnd) error { + return c.insertSessionEnd(sessionID, e.Timestamp) +} + +func (c *PGCache) InsertWebErrorEvent(sessionID uint64, e *ErrorEvent) error { + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + if err := c.Conn.InsertWebErrorEvent(sessionID, session.ProjectID, e); err != nil { + return err + } + session.ErrorsCount += 1 + return nil +} + diff --git a/backend/pkg/db/cache/pg_cache.go b/backend/pkg/db/cache/pg_cache.go new file mode 100644 index 000000000..0ca429eb5 --- /dev/null +++ b/backend/pkg/db/cache/pg_cache.go @@ -0,0 +1,40 @@ +package cache + +import ( + "time" + + "openreplay/backend/pkg/db/postgres" + . "openreplay/backend/pkg/db/types" +) + +type ProjectMeta struct { + *Project + expirationTime time.Time +} + +// !TODO: remove old sessions by timeout to avoid memleaks + +/* + * Cache layer around the stateless PG adapter +**/ +type PGCache struct { + *postgres.Conn + sessions map[uint64]*Session + projects map[uint32]*ProjectMeta + projectsByKeys map[string]*ProjectMeta + projectExpirationTimeout time.Duration +} + +// TODO: create conn automatically +func NewPGCache(pgConn *postgres.Conn, projectExpirationTimeoutMs int64) *PGCache { + return &PGCache{ + Conn: pgConn, + sessions: make(map[uint64]*Session), + projects: make(map[uint32]*ProjectMeta), + projectsByKeys: make(map[string]*ProjectMeta), + projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs), + } +} + + + diff --git a/backend/pkg/db/cache/project.go b/backend/pkg/db/cache/project.go new file mode 100644 index 000000000..1411e608b --- /dev/null +++ b/backend/pkg/db/cache/project.go @@ -0,0 +1,37 @@ +package cache + +import ( + "time" + . "openreplay/backend/pkg/db/types" +) + +func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) { + if c.projectsByKeys[ projectKey ] != nil && + time.Now().Before(c.projectsByKeys[ projectKey ].expirationTime) { + return c.projectsByKeys[ projectKey ].Project, nil + } + p, err := c.Conn.GetProjectByKey(projectKey) + if err != nil { + return nil, err + } + c.projectsByKeys[ projectKey ] = &ProjectMeta{ p, time.Now().Add(c.projectExpirationTimeout) } + c.projects[ p.ProjectID ] = c.projectsByKeys[ projectKey ] + return p, nil +} + + + +func (c *PGCache) GetProject(projectID uint32) (*Project, error) { + if c.projects[ projectID ] != nil && + time.Now().Before(c.projects[ projectID ].expirationTime) { + return c.projects[ projectID ].Project, nil + } + p, err := c.Conn.GetProject(projectID) + if err != nil { + return nil, err + } + c.projects[ projectID ] = &ProjectMeta{ p, time.Now().Add(c.projectExpirationTimeout) } + c.projectsByKeys[ p.ProjectKey ] = c.projects[ projectID ] + return p, nil +} + diff --git a/backend/pkg/db/cache/session.go b/backend/pkg/db/cache/session.go new file mode 100644 index 000000000..2038fd1bd --- /dev/null +++ b/backend/pkg/db/cache/session.go @@ -0,0 +1,30 @@ +package cache + +import ( + "github.com/jackc/pgx/v4" + + . "openreplay/backend/pkg/db/types" +) + +func (c *PGCache) GetSession(sessionID uint64) (*Session, error) { + if s, inCache := c.sessions[ sessionID ]; inCache { + // TODO: review. Might cause bugs in case of multiple instances + if s == nil { + return nil, pgx.ErrNoRows + } + return s, nil + } + s, err := c.Conn.GetSession(sessionID) + if err == pgx.ErrNoRows { + c.sessions[ sessionID ] = nil + } + if err != nil { + return nil, err + } + c.sessions[ sessionID ] = s + return s, nil +} + +func (c *PGCache) DeleteSession(sessionID uint64) { + delete(c.sessions, sessionID) +} diff --git a/backend/pkg/db/postgres/alert.go b/backend/pkg/db/postgres/alert.go new file mode 100644 index 000000000..e00ecf953 --- /dev/null +++ b/backend/pkg/db/postgres/alert.go @@ -0,0 +1,240 @@ +package postgres + +import ( + "database/sql" + "errors" + "fmt" + sq "github.com/Masterminds/squirrel" + "log" + "strconv" + "time" +) + +type TimeString sql.NullString +type query struct { + Left string `db:"query.left" json:"left"` + Operator string `db:"query.operator" json:"operator"` + Right float64 `db:"query.right" json:"right"` +} +type options struct { + RenotifyInterval int64 `db:"options.renotifyInterval" json:"renotifyInterval"` + LastNotification int64 `db:"options.lastNotification" json:"lastNotification;omitempty"` + CurrentPeriod int64 `db:"options.currentPeriod" json:"currentPeriod"` + PreviousPeriod int64 `db:"options.previousPeriod" json:"previousPeriod;omitempty"` + Message []map[string]string `db:"options.message" json:"message;omitempty"` + Change string `db:"options.change" json:"change;omitempty"` +} +type Alert struct { + AlertID uint32 `db:"alert_id" json:"alert_id"` + ProjectID uint32 `db:"project_id" json:"project_id"` + Name string `db:"name" json:"name"` + Description sql.NullString `db:"description" json:"description"` + Active bool `db:"active" json:"active"` + DetectionMethod string `db:"detection_method" json:"detection_method"` + Query query `db:"query" json:"query"` + DeletedAt *int64 `db:"deleted_at" json:"deleted_at"` + CreatedAt *int64 `db:"created_at" json:"created_at"` + Options options `db:"options" json:"options"` + TenantId uint32 `db:"tenant_id" json:"tenant_id"` +} + +func (pg *Conn) IterateAlerts(iter func(alert *Alert, err error)) error { + rows, err := pg.query(` + SELECT + alerts.alert_id, + alerts.project_id, + alerts.name, + alerts.description, + alerts.active, + alerts.detection_method, + alerts.query, + CAST(EXTRACT(epoch FROM alerts.deleted_at) * 1000 AS BIGINT) AS deleted_at, + CAST(EXTRACT(epoch FROM alerts.created_at) * 1000 AS BIGINT) AS created_at, + alerts.options, + projects.tenant_id + FROM public.alerts INNER JOIN public.projects USING(project_id) + WHERE alerts.active AND alerts.deleted_at ISNULL; + `) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + a := new(Alert) + if err = rows.Scan( + &a.AlertID, + &a.ProjectID, + &a.Name, + &a.Description, + &a.Active, + &a.DetectionMethod, + &a.Query, + &a.DeletedAt, + &a.CreatedAt, + &a.Options, + &a.TenantId, + ); err != nil { + iter(nil, err) + continue + } + iter(a, nil) + } + + if err = rows.Err(); err != nil { + return err + } + return nil +} + +func (pg *Conn) SaveLastNotification(allIds []uint32) error { + var paramrefs string + for _, v := range allIds { + paramrefs += strconv.Itoa(int(v)) + `,` + } + paramrefs = paramrefs[:len(paramrefs)-1] // remove last "," + q := "UPDATE public.Alerts SET options = options||'{\"lastNotification\":" + strconv.Itoa(int(time.Now().Unix()*1000)) + "}'::jsonb WHERE alert_id IN (" + paramrefs + ");" + //log.Println(q) + log.Println("Updating PG") + return pg.exec(q) +} + +type columnDefinition struct { + table string + formula string + condition string + group string +} + +var LeftToDb = map[string]columnDefinition{ + "performance.dom_content_loaded.average": {table: "pages", formula: "COALESCE(AVG(NULLIF(dom_content_loaded_event_start ,0)),0)"}, + "performance.first_meaningful_paint.average": {table: "pages", formula: "COALESCE(AVG(NULLIF(first_contentful_paint,0)),0)"}, + "performance.page_load_time.average": {table: "pages", formula: "AVG(NULLIF(load_event_end ,0))"}, + "performance.dom_build_time.average": {table: "pages", formula: "AVG(NULLIF(dom_building_time,0))"}, + "performance.speed_index.average": {table: "pages", formula: "AVG(NULLIF(speed_index,0))"}, + //"avgSpeedIndexByLocation": {table: "pages", formula: "AVG(NULLIF(speed_index,0))", group: "user_country"}, + "performance.page_response_time.average": {table: "pages", formula: "AVG(NULLIF(response_time,0))"}, + "performance.ttfb.average": {table: "pages", formula: "AVG(NULLIF(first_paint,0))"}, + //"avgDomContentLoaded": {table: "pages", formula: "AVG(NULLIF(dom_content_loaded_event_time,0))"}, + "performance.time_to_render.averag": {table: "pages", formula: "AVG(NULLIF(visually_complete,0))"}, + "performance.image_load_time.average": {table: "resources", formula: "AVG(NULLIF(duration,0))", condition: "type=='img'"}, + "performance.request_load_time.average": {table: "resources", formula: "AVG(NULLIF(duration,0))", condition: "type=='fetch'"}, + "resources.load_time.average": {table: "resources", formula: "AVG(NULLIF(duration,0))"}, + "resources.missing.count": {table: "resources", formula: "COUNT(DISTINCT url_hostpath)", condition: "success==0"}, + "errors.4xx_5xx.count": {table: "resources", formula: "COUNT(session_id)", condition: "intDiv(status, 100)!=2"}, + "errors.4xx.count": {table: "resources", formula: "COUNT(session_id)", condition: "intDiv(status, 100)==4"}, + "errors.5xx.count": {table: "resources", formula: "COUNT(session_id)", condition: "intDiv(status, 100)==5"}, + "errors.javascript.impacted_sessions.count": {table: "resources", formula: "COUNT(DISTINCT session_id)", condition: "success=0 AND type='script'"}, + "performance.crashes.count": {table: "sessions", formula: "COUNT(DISTINCT session_id)", condition: "errors_count > 0"}, + "errors.javascript.count": {table: "errors", formula: "COUNT(DISTINCT session_id)", condition: "source=='js_exception'"}, + "errors.backend.count": {table: "errors", formula: "COUNT(DISTINCT session_id)", condition: "source!='js_exception'"}, +} + +//This is the frequency of execution for each threshold +var TimeInterval = map[int64]int64{ + 15: 3, + 30: 5, + 60: 10, + 120: 20, + 240: 30, + 1440: 60, +} + +func (a *Alert) CanCheck() bool { + now := time.Now().Unix() * 1000 + var repetitionBase int64 + + if repetitionBase = a.Options.CurrentPeriod; a.DetectionMethod == "change" && a.Options.CurrentPeriod > a.Options.PreviousPeriod { + repetitionBase = a.Options.PreviousPeriod + } + + if _, ok := TimeInterval[repetitionBase]; !ok { + log.Printf("repetitionBase: %d NOT FOUND", repetitionBase) + return false + } + //for i := int64(0); i <= 10; i++ { + // now += 60 * 1000 + // log.Printf("%s: ((now-*a.CreatedAt)%%TimeInterval[repetitionBase]*60*1000) < 60*1000: %t", a.Name, ((now-*a.CreatedAt)%(TimeInterval[repetitionBase]*60*1000)) < 60*1000) + // log.Printf("now: %d", now) + // log.Printf("*a.CreatedAt: %d", *a.CreatedAt) + // log.Printf("now-*a.CreatedAt: %d", now-*a.CreatedAt) + // log.Printf("(now-*a.CreatedAt)%%TimeInterval[repetitionBase]*60*1000: %d", (now-*a.CreatedAt)%TimeInterval[repetitionBase]*60*1000) + //} + //return false + //log.Printf("%s: a.Options.RenotifyInterval<=0: %t", a.Name, a.Options.RenotifyInterval <= 0) + //log.Printf("%s: a.Options.LastNotification <= 0: %t", a.Name, a.Options.LastNotification <= 0) + //log.Printf("%s: (now-a.Options.LastNotification) > a.Options.RenotifyInterval*60*1000: %t", a.Name, (now-a.Options.LastNotification) > a.Options.RenotifyInterval*60*1000) + //log.Printf("%s: ((now-*a.CreatedAt)%%TimeInterval[repetitionBase]*60*1000) < 60*1000: %t", a.Name, ((now-*a.CreatedAt)%TimeInterval[repetitionBase]*60*1000) < 60*1000) + //log.Printf("%s: TimeInterval[repetitionBase]: %d", a.Name, TimeInterval[repetitionBase]) + return a.DeletedAt == nil && a.Active && + (a.Options.RenotifyInterval <= 0 || + a.Options.LastNotification <= 0 || + ((now - a.Options.LastNotification) > a.Options.RenotifyInterval*60*1000)) && + ((now-*a.CreatedAt)%(TimeInterval[repetitionBase]*60*1000)) < 60*1000 +} + +func (a *Alert) Build() (sq.SelectBuilder, error) { + colDef := LeftToDb[a.Query.Left] + subQ := sq. + Select(colDef.formula + " AS value"). + From(colDef.table). + Where(sq.And{sq.Eq{"project_id": a.ProjectID}, + sq.Expr(colDef.condition)}) + q := sq.Select(fmt.Sprint("value, coalesce(value,0)", a.Query.Operator, a.Query.Right, " AS valid")) + if len(colDef.group) > 0 { + subQ = subQ.Column(colDef.group + " AS group_value") + subQ = subQ.GroupBy(colDef.group) + q = q.Column("group_value") + } + + if a.DetectionMethod == "threshold" { + q = q.FromSelect(subQ.Where(sq.Expr("datetime>=toDateTime(?)", time.Now().Unix()-a.Options.CurrentPeriod*60)), "stat") + } else if a.DetectionMethod == "change" { + if a.Options.Change == "change" { + if len(colDef.group) == 0 { + sub1, args1, _ := subQ.Where(sq.Expr("datetime>=toDateTime(?)", time.Now().Unix()-a.Options.CurrentPeriod*60)).ToSql() + sub2, args2, _ := subQ.Where( + sq.And{ + sq.Expr("datetime=toDateTime(?)", time.Now().Unix()-2*a.Options.CurrentPeriod*60), + }).ToSql() + sub1, _, _ = sq.Expr("SELECT ((" + sub1 + ")-(" + sub2 + ")) AS value").ToSql() + q = q.JoinClause("FROM ("+sub1+") AS stat", append(args1, args2...)...) + } else { + subq1 := subQ.Where(sq.Expr("datetime>=toDateTime(?)", time.Now().Unix()-a.Options.CurrentPeriod*60)) + sub2, args2, _ := subQ.Where( + sq.And{ + sq.Expr("datetime=toDateTime(?)", time.Now().Unix()-2*a.Options.CurrentPeriod*60), + }).ToSql() + sub1 := sq.Select("group_value", "(stat1.value-stat2.value) AS value").FromSelect(subq1, "stat1").JoinClause("INNER JOIN ("+sub2+") AS stat2 USING(group_value)", args2...) + q = q.FromSelect(sub1, "stat") + } + } else if a.Options.Change == "percent" { + if len(colDef.group) == 0 { + sub1, args1, _ := subQ.Where(sq.Expr("datetime>=toDateTime(?)", time.Now().Unix()-a.Options.CurrentPeriod*60)).ToSql() + sub2, args2, _ := subQ.Where( + sq.And{ + sq.Expr("datetime=toDateTime(?)", time.Now().Unix()-a.Options.PreviousPeriod*60-a.Options.CurrentPeriod*60), + }).ToSql() + sub1, _, _ = sq.Expr("SELECT ((" + sub1 + ")/(" + sub2 + ")-1)*100 AS value").ToSql() + q = q.JoinClause("FROM ("+sub1+") AS stat", append(args1, args2...)...) + } else { + subq1 := subQ.Where(sq.Expr("datetime>=toDateTime(?)", time.Now().Unix()-a.Options.CurrentPeriod*60)) + sub2, args2, _ := subQ.Where( + sq.And{ + sq.Expr("datetime=toDateTime(?)", time.Now().Unix()-a.Options.PreviousPeriod*60-a.Options.CurrentPeriod*60), + }).ToSql() + sub1 := sq.Select("group_value", "(stat1.value/stat2.value-1)*100 AS value").FromSelect(subq1, "stat1").JoinClause("INNER JOIN ("+sub2+") AS stat2 USING(group_value)", args2...) + q = q.FromSelect(sub1, "stat") + } + } else { + return q, errors.New("unsupported change method") + } + + } else { + return q, errors.New("unsupported detection method") + } + return q, nil +} diff --git a/backend/pkg/db/postgres/connector.go b/backend/pkg/db/postgres/connector.go new file mode 100644 index 000000000..37e09f812 --- /dev/null +++ b/backend/pkg/db/postgres/connector.go @@ -0,0 +1,63 @@ +package postgres + +import ( + "context" + "log" + + "github.com/jackc/pgx/v4" + "github.com/jackc/pgx/v4/pgxpool" +) + +type Conn struct { + c *pgxpool.Pool // TODO: conditional usage of Pool/Conn (use interface?) +} + +func NewConn(url string) *Conn { + c, err := pgxpool.Connect(context.Background(), url) + if err != nil { + log.Fatalln(err) + } + return &Conn{c} +} + +func (conn *Conn) Close() error { + conn.c.Close() + return nil +} + +func (conn *Conn) query(sql string, args ...interface{}) (pgx.Rows, error) { + return conn.c.Query(context.Background(), sql, args...) +} + +func (conn *Conn) queryRow(sql string, args ...interface{}) pgx.Row { + return conn.c.QueryRow(context.Background(), sql, args...) +} + +func (conn *Conn) exec(sql string, args ...interface{}) error { + _, err := conn.c.Exec(context.Background(), sql, args...) + return err +} + +type _Tx struct { + pgx.Tx +} + +func (conn *Conn) begin() (_Tx, error) { + tx, err := conn.c.Begin(context.Background()) + return _Tx{tx}, err +} + +func (tx _Tx) exec(sql string, args ...interface{}) error { + _, err := tx.Exec(context.Background(), sql, args...) + return err; +} + +func (tx _Tx) rollback() error { + return tx.Rollback(context.Background()) +} + +func (tx _Tx) commit() error { + return tx.Commit(context.Background()) +} + + diff --git a/backend/pkg/db/postgres/errors.go b/backend/pkg/db/postgres/errors.go new file mode 100644 index 000000000..9012bfe6b --- /dev/null +++ b/backend/pkg/db/postgres/errors.go @@ -0,0 +1,16 @@ +package postgres + +import ( + "errors" + + "github.com/jackc/pgconn" + "github.com/jackc/pgerrcode" +) + +func IsPkeyViolation(err error) bool { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UniqueViolation { + return true + } + return false +} \ No newline at end of file diff --git a/backend/pkg/db/postgres/helpers.go b/backend/pkg/db/postgres/helpers.go new file mode 100644 index 000000000..e6e9747e8 --- /dev/null +++ b/backend/pkg/db/postgres/helpers.go @@ -0,0 +1,35 @@ +package postgres + +import ( + "openreplay/backend/pkg/messages" +) + +func getIssueScore(issueEvent *messages.IssueEvent) int { + switch issueEvent.Type { + case "crash", "dead_click", "memory", "cpu": + return 1000 + case "bad_request", "excessive_scrolling", "click_rage", "missing_resource" : + return 500 + case "slow_resource", "slow_page_load": + return 100 + default: + return 100 + } +} + +func calcDomBuildingTime(pe *messages.PageEvent) uint64 { + if pe == nil { + return 0 + } + if pe.DomContentLoadedEventStart < pe.ResponseEnd { + return 0 + } + return pe.DomContentLoadedEventStart - pe.ResponseEnd +} + +func calcResponseTime(pe *messages.PageEvent) uint64 { + if pe.ResponseStart <= pe.ResponseEnd { + return pe.ResponseEnd - pe.ResponseStart + } + return 0 +} \ No newline at end of file diff --git a/backend/pkg/db/postgres/integration.go b/backend/pkg/db/postgres/integration.go new file mode 100644 index 000000000..94351b44d --- /dev/null +++ b/backend/pkg/db/postgres/integration.go @@ -0,0 +1,49 @@ +package postgres + +import ( + "encoding/json" +) + +//go:generate $GOPATH/bin/easytags $GOFILE json + +type Integration struct { + ProjectID uint32 `json:"project_id"` + Provider string `json:"provider"` + //DeletedAt *int64 `json:"deleted_at"` + RequestData json.RawMessage `json:"request_data"` + Options json.RawMessage `json:"options"` +} + +func (pg *Conn) IterateIntegrationsOrdered(iter func(integration *Integration, err error)) error { + rows, err := pg.query(` + SELECT project_id, provider, options, request_data + FROM integrations + `) + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + i := new(Integration) + if err := rows.Scan(&i.ProjectID, &i.Provider, &i.Options, &i.RequestData); err != nil { + iter(nil, err) + continue + } + iter(i, nil) + } + + if err = rows.Err(); err != nil { + return err + } + return nil +} + +func (pg *Conn) UpdateIntegrationRequestData(i *Integration) error { + return pg.exec(` + UPDATE integrations + SET request_data = $1 + WHERE project_id=$2 AND provider=$3`, + i.RequestData, i.ProjectID, i.Provider, + ) +} diff --git a/backend/pkg/db/postgres/listener.go b/backend/pkg/db/postgres/listener.go new file mode 100644 index 000000000..0f6d73ef7 --- /dev/null +++ b/backend/pkg/db/postgres/listener.go @@ -0,0 +1,82 @@ +package postgres + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/jackc/pgx/v4" + + +) + +type Listener struct { + conn *pgx.Conn + Integrations chan *Integration + Alerts chan *Alert + Errors chan error +} + +func NewIntegrationsListener(url string) (*Listener, error) { + conn, err := pgx.Connect(context.Background(), url) + if err != nil { + return nil, err + } + listener := &Listener{ + conn: conn, + Errors: make(chan error), + } + listener.Integrations = make(chan *Integration, 50) + if _, err := conn.Exec(context.Background(), "LISTEN integration"); err != nil { + return nil, err + } + go listener.listen() + return listener, nil +} + +func NewAlertsListener(url string) (*Listener, error) { + conn, err := pgx.Connect(context.Background(), url) + if err != nil { + return nil, err + } + listener := &Listener{ + conn: conn, + Errors: make(chan error), + } + listener.Alerts = make(chan *Alert, 50) + if _, err := conn.Exec(context.Background(), "LISTEN alert"); err != nil { + return nil, err + } + go listener.listen() + return listener, nil +} + +func (listener *Listener) listen() { + for { + notification, err := listener.conn.WaitForNotification(context.Background()) + if err != nil { + listener.Errors <- err + continue + } + switch notification.Channel { + case "integration": + integrationP := new(Integration) + if err := json.Unmarshal([]byte(notification.Payload), integrationP); err != nil { + listener.Errors <- fmt.Errorf("%v | Payload: %v", err, notification.Payload) + } else { + listener.Integrations <- integrationP + } + case "alert": + alertP := new(Alert) + if err := json.Unmarshal([]byte(notification.Payload), alertP); err != nil { + listener.Errors <- fmt.Errorf("%v | Payload: %v", err, notification.Payload) + } else { + listener.Alerts <- alertP + } + } + } +} + +func (listener *Listener) Close() error { + return listener.conn.Close(context.Background()) +} diff --git a/backend/pkg/db/postgres/messages_common.go b/backend/pkg/db/postgres/messages_common.go new file mode 100644 index 000000000..e91af068f --- /dev/null +++ b/backend/pkg/db/postgres/messages_common.go @@ -0,0 +1,224 @@ +package postgres + +import ( + "log" + "strings" + "fmt" + + "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/db/types" +) + +func getAutocompleteType(baseType string, platform string) string { + if platform == "web" { + return baseType + } + return baseType + "_" + strings.ToUpper(platform) + +} + +func (conn *Conn) insertAutocompleteValue(sessionID uint64, tp string, value string) { + if len(value) == 0 { + return + } + if err := conn.exec(` + INSERT INTO autocomplete ( + value, + type, + project_id + ) (SELECT + $1, $2, project_id + FROM sessions + WHERE session_id = $3 + ) ON CONFLICT DO NOTHING`, + value, tp, sessionID, + ); err != nil { + log.Printf("Insert autocomplete error: %v", err) + } +} + +func (conn *Conn) InsertSessionStart(sessionID uint64, s *types.Session) error { + if err := conn.exec(` + INSERT INTO sessions ( + session_id, project_id, start_ts, + user_uuid, user_device, user_device_type, user_country, + user_os, user_os_version, + rev_id, + tracker_version, issue_score, + platform, + user_agent, user_browser, user_browser_version, user_device_memory_size, user_device_heap_size + ) VALUES ( + $1, $2, $3, + $4, $5, $6, $7, + $8, NULLIF($9, ''), + NULLIF($10, ''), + $11, $12, + $13, + NULLIF($14, ''), NULLIF($15, ''), NULLIF($16, ''), NULLIF($17, 0), NULLIF($18, 0::bigint) + )`, + sessionID, s.ProjectID, s.Timestamp, + s.UserUUID, s.UserDevice, s.UserDeviceType, s.UserCountry, + s.UserOS, s.UserOSVersion, + s.RevID, + s.TrackerVersion, s.Timestamp/1000, + s.Platform, + s.UserAgent, s.UserBrowser, s.UserBrowserVersion, s.UserDeviceMemorySize, s.UserDeviceHeapSize, + ); err != nil { + return err; + } + conn.insertAutocompleteValue(sessionID, getAutocompleteType("USEROS", s.Platform), s.UserOS) + conn.insertAutocompleteValue(sessionID, getAutocompleteType("USERDEVICE", s.Platform), s.UserDevice) + conn.insertAutocompleteValue(sessionID, getAutocompleteType("USERCOUNTRY", s.Platform), s.UserCountry) + conn.insertAutocompleteValue(sessionID, getAutocompleteType("REVID", s.Platform), s.RevID) + // s.Platform == "web" + conn.insertAutocompleteValue(sessionID, "USERBROWSER", s.UserBrowser) + return nil +} + +func (conn *Conn) InsertSessionEnd(sessionID uint64, timestamp uint64) (uint64, error) { + // Search acceleration + if err := conn.exec(` + UPDATE sessions + SET issue_types=(SELECT COALESCE(ARRAY_AGG(DISTINCT ps.type), '{}')::issue_type[] + FROM events_common.issues + INNER JOIN issues AS ps USING (issue_id) + WHERE session_id = $1) + WHERE session_id = $1 + `, + sessionID, + ); err != nil { + log.Printf("Error while updating issue_types %v", sessionID) + } + + var dur uint64 + if err := conn.queryRow(` + UPDATE sessions SET duration=$2 - start_ts + WHERE session_id=$1 + RETURNING duration + `, + sessionID, timestamp, + ).Scan(&dur); err != nil { + return 0, err + } + return dur, nil +} + +func (conn *Conn) InsertRequest(sessionID uint64, timestamp uint64, index uint64, url string, duration uint64, success bool) error { + return conn.exec(` + INSERT INTO events_common.requests ( + session_id, timestamp, seq_index, url, duration, success + ) VALUES ( + $1, $2, $3, $4, $5, $6 + )`, + sessionID, timestamp, + getSqIdx(index), + url, duration, success, + ) +} + +func (conn *Conn) InsertCustomEvent(sessionID uint64, timestamp uint64, index uint64, name string, payload string) error { + return conn.exec(` + INSERT INTO events_common.customs ( + session_id, timestamp, seq_index, name, payload + ) VALUES ( + $1, $2, $3, $4, $5 + )`, + sessionID, timestamp, + getSqIdx(index), + name, payload, + ) +} + +func (conn *Conn) InsertUserID(sessionID uint64, userID string) error { + return conn.exec(` + UPDATE sessions SET user_id = $1 + WHERE session_id = $2`, + userID, sessionID, + ) +} + +func (conn *Conn) InsertUserAnonymousID(sessionID uint64, userAnonymousID string) error { + return conn.exec(` + UPDATE sessions SET user_anonymous_id = $1 + WHERE session_id = $2`, + userAnonymousID, sessionID, + ) +} + + +func (conn *Conn) InsertMetadata(sessionID uint64, keyNo uint, value string) error { + return conn.exec(fmt.Sprintf(` + UPDATE sessions SET metadata_%v = $1 + WHERE session_id = $2`, keyNo), + value, sessionID, + ) + // conn.insertAutocompleteValue(sessionID, "METADATA", value) +} + +func (conn *Conn) InsertIssueEvent(sessionID uint64, projectID uint32, e *messages.IssueEvent) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + issueID := hashid.IssueID(projectID, e) + + // TEMP. TODO: nullable & json message field type + payload := &e.Payload; + if *payload == "" || *payload == "{}" { + payload = nil + } + context := &e.Context; + if *context == "" || *context == "{}" { + context = nil + } + + if err = tx.exec(` + INSERT INTO issues ( + project_id, issue_id, type, context_string, context + ) (SELECT + project_id, $2, $3, $4, CAST($5 AS jsonb) + FROM sessions + WHERE session_id = $1 + )ON CONFLICT DO NOTHING`, + sessionID, issueID, e.Type, e.ContextString, context, + ); err != nil { + return err + } + if err = tx.exec(` + INSERT INTO events_common.issues ( + session_id, issue_id, timestamp, seq_index, payload + ) VALUES ( + $1, $2, $3, $4, CAST($5 AS jsonb) + )`, + sessionID, issueID, e.Timestamp, + getSqIdx(e.MessageID), + payload, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET issue_score = issue_score + $2 + WHERE session_id = $1`, + sessionID, getIssueScore(e), + ); err != nil { + return err + } + // TODO: no redundancy. Deliver to UI in a different way + if e.Type == "custom" { + if err = tx.exec(` + INSERT INTO events_common.customs + (session_id, seq_index, timestamp, name, payload, level) + VALUES + ($1, $2, $3, $4, $5, 'error') + `, + sessionID, getSqIdx(e.MessageID), e.Timestamp, e.ContextString, e.Payload, + ); err != nil { + return err + } + } + return tx.commit() +} + + diff --git a/backend/pkg/db/postgres/messages_ios.go b/backend/pkg/db/postgres/messages_ios.go new file mode 100644 index 000000000..b54a88af7 --- /dev/null +++ b/backend/pkg/db/postgres/messages_ios.go @@ -0,0 +1,181 @@ +package postgres + +import ( + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/url" +) + +func (conn *Conn) InsertIOSCustomEvent(sessionID uint64, e *messages.IOSCustomEvent) error { + err := conn.InsertCustomEvent(sessionID, e.Timestamp, e.Index, e.Name, e.Payload) + if err == nil { + conn.insertAutocompleteValue(sessionID, "CUSTOM_IOS", e.Name) + } + return err +} + +func (conn *Conn) InsertIOSUserID(sessionID uint64, userID *messages.IOSUserID) error { + err := conn.InsertUserID(sessionID, userID.Value) + if err == nil { + conn.insertAutocompleteValue(sessionID, "USERID_IOS", userID.Value) + } + return err +} + +func (conn *Conn) InsertIOSUserAnonymousID(sessionID uint64, userAnonymousID *messages.IOSUserAnonymousID) error { + err := conn.InsertUserAnonymousID(sessionID, userAnonymousID.Value) + if err == nil { + conn.insertAutocompleteValue(sessionID, "USERANONYMOUSID_IOS", userAnonymousID.Value) + } + return err +} + +func (conn *Conn) InsertIOSNetworkCall(sessionID uint64, e *messages.IOSNetworkCall) error { + err := conn.InsertRequest(sessionID, e.Timestamp, e.Index, e.URL, e.Duration, e.Success) + if err == nil { + conn.insertAutocompleteValue(sessionID, "REQUEST_IOS", url.DiscardURLQuery(e.URL)) + } + return err +} + +func (conn *Conn) InsertIOSScreenEnter(sessionID uint64, screenEnter *messages.IOSScreenEnter) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + + if err = tx.exec(` + INSERT INTO events_ios.views ( + session_id, timestamp, seq_index, name + ) VALUES ( + $1, $2, $3, $4 + )`, + sessionID, screenEnter.Timestamp, screenEnter.Index, screenEnter.ViewName, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET pages_count = pages_count + 1 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + if err = tx.commit(); err != nil { + return err + } + conn.insertAutocompleteValue(sessionID, "VIEW_IOS", screenEnter.ViewName) + return nil +} + +func (conn *Conn) InsertIOSClickEvent(sessionID uint64, clickEvent *messages.IOSClickEvent) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + + if err = tx.exec(` + INSERT INTO events_ios.clicks ( + session_id, timestamp, seq_index, label + ) VALUES ( + $1, $2, $3, $4 + )`, + sessionID, clickEvent.Timestamp, clickEvent.Index, clickEvent.Label, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET events_count = events_count + 1 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + if err = tx.commit(); err != nil { + return err + } + conn.insertAutocompleteValue(sessionID, "CLICK_IOS", clickEvent.Label) + return nil +} + +func (conn *Conn) InsertIOSInputEvent(sessionID uint64, inputEvent *messages.IOSInputEvent) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + + var value interface{} = inputEvent.Value + if inputEvent.ValueMasked { + value = nil + } + + if err = tx.exec(` + INSERT INTO events_ios.inputs ( + session_id, timestamp, seq_index, label, value + ) VALUES ( + $1, $2, $3, $4, $5 + )`, + sessionID, inputEvent.Timestamp, inputEvent.Index, inputEvent.Label, value, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET events_count = events_count + 1 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + if err = tx.commit(); err != nil { + return err + } + conn.insertAutocompleteValue(sessionID, "INPUT_IOS", inputEvent.Label) + // conn.insertAutocompleteValue(sessionID, "INPUT_VALUE", inputEvent.Label) + return nil +} + +func (conn *Conn) InsertIOSCrash(sessionID uint64, projectID uint32, crash *messages.IOSCrash) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + + crashID := hashid.IOSCrashID(projectID, crash) + + if err = tx.exec(` + INSERT INTO crashes_ios ( + project_id, crash_id, name, reason, stacktrace + ) (SELECT + project_id, $2, $3, $4, $5 + FROM sessions + WHERE session_id = $1 + )ON CONFLICT DO NOTHING`, + sessionID, crashID, crash.Name, crash.Reason, crash.Stacktrace, + ); err != nil { + return err + } + if err = tx.exec(` + INSERT INTO events_ios.crashes ( + session_id, timestamp, seq_index, crash_id + ) VALUES ( + $1, $2, $3, $4 + )`, + sessionID, crash.Timestamp, crash.Index, crashID, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET errors_count = errors_count + 1, issue_score = issue_score + 1000 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + return tx.commit() +} + + diff --git a/backend/pkg/db/postgres/messages_web.go b/backend/pkg/db/postgres/messages_web.go new file mode 100644 index 000000000..a39eb73d5 --- /dev/null +++ b/backend/pkg/db/postgres/messages_web.go @@ -0,0 +1,200 @@ +package postgres + +import ( + "math" + + "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/url" + . "openreplay/backend/pkg/messages" +) + +// TODO: change messages and replace everywhere to e.Index +func getSqIdx(messageID uint64) uint { + return uint(messageID % math.MaxInt32) +} + + +func (conn *Conn) InsertWebCustomEvent(sessionID uint64, e *CustomEvent) error { + err := conn.InsertCustomEvent(sessionID, e.Timestamp, + e.MessageID, + e.Name, e.Payload) + if err == nil { + conn.insertAutocompleteValue(sessionID, "CUSTOM", e.Name) + } + return err +} + +func (conn *Conn) InsertWebUserID(sessionID uint64, userID *UserID) error { + err := conn.InsertUserID(sessionID, userID.ID) + if err == nil { + conn.insertAutocompleteValue(sessionID, "USERID", userID.ID) + } + return err +} + +func (conn *Conn) InsertWebUserAnonymousID(sessionID uint64, userAnonymousID *UserAnonymousID) error { + err := conn.InsertUserAnonymousID(sessionID, userAnonymousID.ID) + if err == nil { + conn.insertAutocompleteValue(sessionID, "USERANONYMOUSID", userAnonymousID.ID) + } + return err +} + +func (conn *Conn) InsertWebResourceEvent(sessionID uint64, e *ResourceEvent) error { + if e.Type != "fetch" { + return nil + } + err := conn.InsertRequest(sessionID, e.Timestamp, + e.MessageID, + e.URL, e.Duration, e.Success, + ) + if err == nil { + conn.insertAutocompleteValue(sessionID, "REQUEST", url.DiscardURLQuery(e.URL)) + } + return err +} + +// TODO: fix column "dom_content_loaded_event_end" of relation "pages" +func (conn *Conn) InsertWebPageEvent(sessionID uint64, e *PageEvent) error { + host, path, err := url.GetURLParts(e.URL) + if err != nil { + return err + } + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + if err := tx.exec(` + INSERT INTO events.pages ( + session_id, message_id, timestamp, referrer, base_referrer, host, path, base_path, + dom_content_loaded_time, load_time, response_end, first_paint_time, first_contentful_paint_time, speed_index, visually_complete, time_to_interactive, + response_time, dom_building_time + ) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, + NULLIF($9, 0), NULLIF($10, 0), NULLIF($11, 0), NULLIF($12, 0), NULLIF($13, 0), NULLIF($14, 0), NULLIF($15, 0), NULLIF($16, 0), + NULLIF($17, 0), NULLIF($18, 0) + ) + `, + sessionID, e.MessageID, e.Timestamp, e.Referrer, url.DiscardURLQuery(e.Referrer), host, path, url.DiscardURLQuery(path), + e.DomContentLoadedEventEnd, e.LoadEventEnd, e.ResponseEnd, e.FirstPaint, e.FirstContentfulPaint, e.SpeedIndex, e.VisuallyComplete, e.TimeToInteractive, + calcResponseTime(e), calcDomBuildingTime(e), + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET pages_count = pages_count + 1 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + if err = tx.commit(); err != nil { + return err + } + conn.insertAutocompleteValue(sessionID, url.DiscardURLQuery(path), "LOCATION") + conn.insertAutocompleteValue(sessionID, url.DiscardURLQuery(e.Referrer), "REFERRER") + return nil +} + +func (conn *Conn) InsertWebClickEvent(sessionID uint64, e *ClickEvent) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + if err = tx.exec(` + INSERT INTO events.clicks + (session_id, message_id, timestamp, label) + VALUES + ($1, $2, $3, NULLIF($4, '')) + `, + sessionID, e.MessageID, e.Timestamp, e.Label, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET events_count = events_count + 1 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + if err = tx.commit(); err != nil { + return err + } + conn.insertAutocompleteValue(sessionID, e.Label, "CLICK") + return nil +} + + +func (conn *Conn) InsertWebInputEvent(sessionID uint64, e *InputEvent) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + value := &e.Value + if e.ValueMasked { + value = nil + } + if err = tx.exec(` + INSERT INTO events.inputs + (session_id, message_id, timestamp, value, label) + VALUES + ($1, $2, $3, $4, NULLIF($5,'')) + `, + sessionID, e.MessageID, e.Timestamp, value, e.Label, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET events_count = events_count + 1 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + if err = tx.commit(); err != nil { + return err + } + conn.insertAutocompleteValue(sessionID, e.Label, "INPUT") + return nil +} + +func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *ErrorEvent) error { + tx, err := conn.begin() + if err != nil { + return err + } + defer tx.rollback() + errorID := hashid.WebErrorID(projectID, e) + if err = tx.exec(` + INSERT INTO errors + (error_id, project_id, source, name, message, payload) + VALUES + ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING`, + errorID, projectID, e.Source, e.Name, e.Message, e.Payload, + ); err != nil { + return err + } + if err = tx.exec(` + INSERT INTO events.errors + (session_id, message_id, timestamp, error_id) + VALUES + ($1, $2, $3, $4) + `, + sessionID, e.MessageID, e.Timestamp, errorID, + ); err != nil { + return err + } + if err = tx.exec(` + UPDATE sessions SET errors_count = errors_count + 1, issue_score = issue_score + 1000 + WHERE session_id = $1`, + sessionID, + ); err != nil { + return err + } + return tx.commit() +} diff --git a/backend/pkg/db/postgres/messages_web_stats.go b/backend/pkg/db/postgres/messages_web_stats.go new file mode 100644 index 000000000..9e3b5bc77 --- /dev/null +++ b/backend/pkg/db/postgres/messages_web_stats.go @@ -0,0 +1,68 @@ +package postgres + +import ( + "openreplay/backend/pkg/url" + . "openreplay/backend/pkg/messages" +) + + + +func (conn *Conn) InsertWebStatsLongtask(sessionID uint64, l *LongTask) error { + return nil // Do we even use them? + // conn.exec(``); +} + + +func (conn *Conn) InsertWebStatsPerformance(sessionID uint64, p *PerformanceTrackAggr) error { + timestamp := (p.TimestampEnd + p.TimestampStart) /2 + return conn.exec(` + INSERT INTO events.performance ( + session_id, timestamp, message_id, + min_fps, avg_fps, max_fps, + min_cpu, avg_cpu, max_cpu, + min_total_js_heap_size, avg_total_js_heap_size, max_total_js_heap_size, + min_used_js_heap_size, avg_used_js_heap_size, max_used_js_heap_size + ) VALUES ( + $1, $2, $3, + $4, $5, $6, + $7, $8, $9, + $10, $11, $12, + $13, $14, $15 + )`, + sessionID, timestamp, timestamp, // ??? TODO: primary key by timestamp+session_id + p.MinFPS, p.AvgFPS, p.MaxFPS, + p.MinCPU, p.AvgCPU, p.MinCPU, + p.MinTotalJSHeapSize, p.AvgTotalJSHeapSize, p.MaxTotalJSHeapSize, + p.MinUsedJSHeapSize, p.AvgUsedJSHeapSize, p.MaxUsedJSHeapSize, + ); +} + +func (conn *Conn) InsertWebStatsResourceEvent(sessionID uint64, e *ResourceEvent) error { + host, _, err := url.GetURLParts(e.URL) + if err != nil { + return err + } + return conn.exec(` + INSERT INTO events.resources ( + session_id, timestamp, message_id, + type, + url, url_host, url_hostpath, + success, status, + method, + duration, ttfb, header_size, encoded_body_size, decoded_body_size + ) VALUES ( + $1, $2, $3, + $4, + $5, $6, $7, + $8, $9, + NULLIF($10, '')::events.resource_method, + NULLIF($11, 0), NULLIF($12, 0), NULLIF($13, 0), NULLIF($14, 0), NULLIF($15, 0) + )`, + sessionID, e.Timestamp, e.MessageID, + e.Type, + e.URL, host, url.DiscardURLQuery(e.URL), + e.Success, e.Status, + url.EnsureMethod(e.Method), + e.Duration, e.TTFB, e.HeaderSize, e.EncodedBodySize, e.DecodedBodySize, + ) +} \ No newline at end of file diff --git a/backend/pkg/db/postgres/notification.go b/backend/pkg/db/postgres/notification.go new file mode 100644 index 000000000..063e92f7b --- /dev/null +++ b/backend/pkg/db/postgres/notification.go @@ -0,0 +1,60 @@ +package postgres + +import ( + "bytes" + "encoding/json" + "log" + "net/http" +) + +//go:generate $GOPATH/bin/easytags $GOFILE json + +type TenantNotification struct { + TenantId uint32 `db:"tenant_id" json:"tenantId"` + Title string `db:"title" json:"title"` + Description string `db:"description" json:"description"` + ButtonText string `db:"button_text" json:"buttonText"` + ButtonUrl string `db:"button_url" json:"buttonUrl"` + ImageUrl *string `db:"image_url" json:"imageUrl"` + Options map[string]interface{} `db:"options" json:"options"` +} + +type Notifications struct { + Notifications []*TenantNotification `json:"notifications"` + Token string `json:"token"` +} + +func (n *Notifications) Send(url string) { + n.Token = "nF46JdQqAM5v9KI9lPMpcu8o9xiJGvNNWOGL7TJP" + body, err := json.Marshal(n) + if err != nil { + log.Println(err) + return + } + //log.Println("------------ Sending a new notification") + req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) + if err != nil { + log.Printf("error in POST notifications: %v\n", err) + return + } + //req.Header.Set("X-Custom-Header", "myvalue") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + //log.Println("response Status:", resp.Status) + //log.Println("response Headers:", resp.Header) + //respBody, _ := ioutil.ReadAll(resp.Body) + //log.Println("response Body:", string(respBody)) +} + +func (n TenantNotification) Send(url string) { + body := Notifications{ + Notifications: []*TenantNotification{&n}, + } + body.Send(url) +} diff --git a/backend/pkg/db/postgres/project.go b/backend/pkg/db/postgres/project.go new file mode 100644 index 000000000..461db66fb --- /dev/null +++ b/backend/pkg/db/postgres/project.go @@ -0,0 +1,45 @@ +package postgres + +import ( + "github.com/jackc/pgx/v4" + . "openreplay/backend/pkg/db/types" +) + +func (conn *Conn) GetProjectByKey(projectKey string) (*Project, error) { + p := &Project{ ProjectKey: projectKey } + if err := conn.queryRow(` + SELECT max_session_duration, sample_rate, project_id + FROM projects + WHERE project_key=$1 AND active = true + `, + projectKey, + ).Scan(&p.MaxSessionDuration, &p.SampleRate, &p.ProjectID); err != nil { + if err == pgx.ErrNoRows { + err = nil + } + return nil, err + } + return p, nil +} + +// TODO: logical separation of metadata +func (conn *Conn) GetProject(projectID uint32) (*Project, error) { + p := &Project{ ProjectID: projectID } + if err := conn.queryRow(` + SELECT project_key, max_session_duration, + metadata_1, metadata_2, metadata_3, metadata_4, metadata_5, + metadata_6, metadata_7, metadata_8, metadata_9, metadata_10 + FROM projects + WHERE project_id=$1 AND active = true + `, + projectID, + ).Scan(&p.ProjectKey,&p.MaxSessionDuration, + &p.Metadata1, &p.Metadata2, &p.Metadata3, &p.Metadata4, &p.Metadata5, + &p.Metadata6, &p.Metadata7, &p.Metadata8, &p.Metadata9, &p.Metadata10); err != nil { + if err == pgx.ErrNoRows { + err = nil + } + return nil, err + } + return p, nil +} \ No newline at end of file diff --git a/backend/pkg/db/postgres/session.go b/backend/pkg/db/postgres/session.go new file mode 100644 index 000000000..c2e731088 --- /dev/null +++ b/backend/pkg/db/postgres/session.go @@ -0,0 +1,106 @@ +package postgres + +//import . "openreplay/backend/pkg/messages" +import . "openreplay/backend/pkg/db/types" +//import "log" + +func (conn *Conn) GetSession(sessionID uint64) (*Session, error) { + s := &Session{ SessionID: sessionID } + var revID, userOSVersion *string + if err := conn.queryRow(` + SELECT platform, + duration, project_id, start_ts, + user_uuid, user_os, user_os_version, + user_device, user_device_type, user_country, + rev_id, tracker_version, + user_id, user_anonymous_id, + metadata_1, metadata_2, metadata_3, metadata_4, metadata_5, + metadata_6, metadata_7, metadata_8, metadata_9, metadata_10 + FROM sessions + WHERE session_id=$1 + `, + sessionID, + ).Scan(&s.Platform, + &s.Duration, &s.ProjectID, &s.Timestamp, + &s.UserUUID, &s.UserOS, &userOSVersion, + &s.UserDevice, &s.UserDeviceType, &s.UserCountry, + &revID, &s.TrackerVersion, + &s.UserID, &s.UserAnonymousID, + &s.Metadata1, &s.Metadata2, &s.Metadata3, &s.Metadata4, &s.Metadata5, + &s.Metadata6, &s.Metadata7, &s.Metadata8, &s.Metadata9, &s.Metadata10); err != nil { + return nil, err + } + if userOSVersion != nil { // TODO: choose format, make f + s.UserOSVersion = *userOSVersion + } + if revID != nil { + s.RevID = *revID + } + return s, nil +} + +// func (conn *Conn) GetSessionClickEvents(sessionID uint64) (list []IOSClickEvent, err error) { +// rows, err := conn.query(` +// SELECT +// timestamp, seq_index, label +// FROM events_ios.clicks +// WHERE session_id=$1 +// `, sessionID) +// if err != nil { +// return err +// } +// defer rows.Close() +// for rows.Next() { +// e := new(IOSClickEvent) +// if err = rows.Scan(&e.Timestamp, &e.Index, &e.Label); err != nil { +// log.Printf("Error while scanning click events: %v", err) +// } else { +// list = append(list, e) +// } +// } +// return list +// } + +// func (conn *Conn) GetSessionInputEvents(sessionID uint64) (list []IOSInputEvent, err error) { +// rows, err := conn.query(` +// SELECT +// timestamp, seq_index, label, value +// FROM events_ios.inputs +// WHERE session_id=$1 +// `, sessionID) +// if err != nil { +// return err +// } +// defer rows.Close() +// for rows.Next() { +// e := new(IOSInputEvent) +// if err = rows.Scan(&e.Timestamp, &e.Index, &e.Label, &e.Value); err != nil { +// log.Printf("Error while scanning click events: %v", err) +// } else { +// list = append(list, e) +// } +// } +// return list +// } + +// func (conn *Conn) GetSessionCrashEvents(sessionID uint64) (list []IOSCrash, err error) { +// rows, err := conn.query(` +// SELECT +// timestamp, seq_index +// FROM events_ios.crashes +// WHERE session_id=$1 +// `, sessionID) +// if err != nil { +// return err +// } +// defer rows.Close() +// for rows.Next() { +// e := new(IOSCrash) +// if err = rows.Scan(&e.Timestamp, &e.Index, &e.Label, &e.Value); err != nil { +// log.Printf("Error while scanning click events: %v", err) +// } else { +// list = append(list, e) +// } +// } +// return list +// } \ No newline at end of file diff --git a/backend/pkg/db/postgres/unstarted_session.go b/backend/pkg/db/postgres/unstarted_session.go new file mode 100644 index 000000000..162946e97 --- /dev/null +++ b/backend/pkg/db/postgres/unstarted_session.go @@ -0,0 +1,45 @@ +package postgres + +type UnstartedSession struct { + ProjectKey string + TrackerVersion string + DoNotTrack bool + Platform string + UserAgent string + UserOS string + UserOSVersion string + UserBrowser string + UserBrowserVersion string + UserDevice string + UserDeviceType string + UserCountry string +} + +func (conn *Conn) InsertUnstartedSession(s UnstartedSession) error { + return conn.exec(` + INSERT INTO unstarted_sessions ( + project_id, + tracker_version, do_not_track, + platform, user_agent, + user_os, user_os_version, + user_browser, user_browser_version, + user_device, user_device_type, + user_country + ) VALUES ( + (SELECT project_id FROM projects WHERE project_key = $1), + $2, $3, + $4, $5, + $6, $7, + $8, $9, + $10, $11, + $12 + )`, + s.ProjectKey, + s.TrackerVersion, s.DoNotTrack, + s.Platform, s.UserAgent, + s.UserOS, s.UserOSVersion, + s.UserBrowser, s.UserBrowserVersion, + s.UserDevice, s.UserDeviceType, + s.UserCountry, + ) +} diff --git a/backend/pkg/db/types/project.go b/backend/pkg/db/types/project.go new file mode 100644 index 000000000..9a267d0c0 --- /dev/null +++ b/backend/pkg/db/types/project.go @@ -0,0 +1,53 @@ +package types + +type Project struct { + ProjectID uint32 + ProjectKey string + MaxSessionDuration int64 + SampleRate byte + Metadata1 *string + Metadata2 *string + Metadata3 *string + Metadata4 *string + Metadata5 *string + Metadata6 *string + Metadata7 *string + Metadata8 *string + Metadata9 *string + Metadata10 *string +} + + +func (p *Project) GetMetadataNo(key string) uint { + if p.Metadata1 != nil && *(p.Metadata1) == key { + return 1 + } + if p.Metadata2 != nil && *(p.Metadata2) == key { + return 2 + } + if p.Metadata3 != nil && *(p.Metadata3) == key { + return 3 + } + if p.Metadata4 != nil && *(p.Metadata4) == key { + return 4 + } + if p.Metadata5 != nil && *(p.Metadata5) == key { + return 5 + } + if p.Metadata6 != nil && *(p.Metadata6) == key { + return 6 + } + if p.Metadata7 != nil && *(p.Metadata7) == key { + return 7 + } + if p.Metadata8 != nil && *(p.Metadata8) == key { + return 8 + } + if p.Metadata9 != nil && *(p.Metadata9) == key { + return 9 + } + if p.Metadata10 != nil && *(p.Metadata10) == key { + return 10 + } + return 0 +} diff --git a/backend/pkg/db/types/session.go b/backend/pkg/db/types/session.go new file mode 100644 index 000000000..0205f76f3 --- /dev/null +++ b/backend/pkg/db/types/session.go @@ -0,0 +1,65 @@ +package types + +type Session struct { + SessionID uint64 + Timestamp uint64 + ProjectID uint32 + TrackerVersion string + RevID string + UserUUID string + UserOS string + UserOSVersion string + UserDevice string + UserCountry string + + Duration *uint64 + PagesCount int + EventsCount int + ErrorsCount int + UserID *string + UserAnonymousID *string + Metadata1 *string + Metadata2 *string + Metadata3 *string + Metadata4 *string + Metadata5 *string + Metadata6 *string + Metadata7 *string + Metadata8 *string + Metadata9 *string + Metadata10 *string + + Platform string + // Only-web properties + UserAgent string + UserBrowser string + UserBrowserVersion string + UserDeviceType string + UserDeviceMemorySize uint64 + UserDeviceHeapSize uint64 +} + +func (s *Session) SetMetadata(keyNo uint, value string) { + switch (keyNo) { + case 1: + s.Metadata1 = &value + case 2: + s.Metadata2 = &value + case 3: + s.Metadata3 = &value + case 4: + s.Metadata4 = &value + case 5: + s.Metadata5 = &value + case 6: + s.Metadata6 = &value + case 7: + s.Metadata7 = &value + case 8: + s.Metadata8 = &value + case 9: + s.Metadata9 = &value + case 10: + s.Metadata10 = &value + } +} \ No newline at end of file diff --git a/backend/pkg/dev/profiling/profiling.go b/backend/pkg/dev/profiling/profiling.go new file mode 100644 index 000000000..139aaeac6 --- /dev/null +++ b/backend/pkg/dev/profiling/profiling.go @@ -0,0 +1,37 @@ +package profiling + +import ( + "log" + "net/http" + "github.com/gorilla/mux" + _ "net/http/pprof" +) + +func Profile() { + go func() { + router := mux.NewRouter() + router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux) + log.Println("Starting profiler...") + if err := http.ListenAndServe(":6060", router); err != nil { + panic(err) + } + }() +} + + +/* + +docker run -p 6060:6060 -e REQUIRED_ENV=http://value -e ANOTHER_ENV=anothervalue workername + +THEN +go tool pprof http://localhost:6060/debug/pprof/heap +OR +go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30 + +(Look up https://golang.org/pkg/net/http/pprof/) + + +THEN +https://www.speedscope.app/ + +*/ \ No newline at end of file diff --git a/backend/pkg/env/aws.go b/backend/pkg/env/aws.go new file mode 100644 index 000000000..dd277f2b1 --- /dev/null +++ b/backend/pkg/env/aws.go @@ -0,0 +1,29 @@ +package env + +import ( + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + _session "github.com/aws/aws-sdk-go/aws/session" +) + +func AWSSessionOnRegion(region string) *_session.Session { + AWS_ACCESS_KEY_ID := String("AWS_ACCESS_KEY_ID") + AWS_SECRET_ACCESS_KEY := String("AWS_SECRET_ACCESS_KEY") + config := &aws.Config{ + Region: aws.String(region), + Credentials: credentials.NewStaticCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, ""), + } + AWS_ENDPOINT := StringOptional("AWS_ENDPOINT") + if AWS_ENDPOINT != "" { + config.Endpoint = aws.String(AWS_ENDPOINT) + config.DisableSSL = aws.Bool(true) + config.S3ForcePathStyle = aws.Bool(true) + } + aws_session, err := _session.NewSession(config) + if err != nil { + log.Fatalf("AWS session error: %v\n", err) + } + return aws_session +} diff --git a/backend/pkg/env/fargate.go b/backend/pkg/env/fargate.go new file mode 100644 index 000000000..b0f1da9ca --- /dev/null +++ b/backend/pkg/env/fargate.go @@ -0,0 +1,41 @@ +package env + +import ( + "encoding/json" + "errors" + "net" + "net/http" + "os" +) + +type fargateTaskContainer struct { + Networks []struct { + IPv4Addresses []string + } +} + +func fargateTaskIP() (net.IP, error) { + res, err := http.Get(os.Getenv("ECS_CONTAINER_METADATA_URI")) + if err != nil { + return nil, err + } + defer res.Body.Close() + + container := fargateTaskContainer{} + if err := json.NewDecoder(res.Body).Decode(&container); err != nil { + return nil, err + } + if len(container.Networks) != 1 { + return nil, errors.New("container should have exactly one network") + } + network := container.Networks[0] + if len(network.IPv4Addresses) != 1 { + return nil, errors.New("container should have exactly one IPv4") + } + + ip := net.ParseIP(network.IPv4Addresses[0]).To4() + if ip == nil { + return nil, errors.New("invalid ip address") + } + return ip, nil +} diff --git a/backend/pkg/env/vars.go b/backend/pkg/env/vars.go new file mode 100644 index 000000000..e6541d002 --- /dev/null +++ b/backend/pkg/env/vars.go @@ -0,0 +1,48 @@ +package env + +import ( + "log" + "os" + "strconv" +) + +func String(key string) string { + v := os.Getenv(key) + if v == "" { + log.Fatalln(key + " is missing") + } + return v +} + +func StringOptional(key string) string { + return os.Getenv(key) +} + +func Uint16(key string) uint16 { + v := String(key) + n, _ := strconv.ParseUint(v, 10, 16) + if n == 0 { + log.Fatalln(key + " has a wrong value") + } + return uint16(n) +} + +func Uint64(key string) uint64 { + v := String(key) + n, _ := strconv.ParseUint(v, 10, 64) + if n == 0 { + log.Fatalln(key + " has a wrong value") + } + return n +} + +func Bool(key string) bool { + v := String(key) + if v != "true" && v != "false" { + log.Fatalln(key + " has wrong value. Accepted only true or false") + } + if v == "true" { + return true + } + return false +} \ No newline at end of file diff --git a/backend/pkg/env/worker_id.go b/backend/pkg/env/worker_id.go new file mode 100644 index 000000000..47fdffc43 --- /dev/null +++ b/backend/pkg/env/worker_id.go @@ -0,0 +1,22 @@ +package env + +import ( + "log" +) + +func hashHostname(hostname string) uint16 { + var h uint16 ; + for i, b := range hostname { + h += uint16(i+1)*uint16(b) + } + return h +} + +func WorkerID() uint16 { + ip, err := fargateTaskIP() + if err != nil { + log.Printf("Warning: unable to retrieve Fargate Task IP: %v; trying to use HOSTNAME instead", err) + return hashHostname(String("HOSTNAME")) + } + return uint16(ip[2])<<8 + uint16(ip[3]) +} diff --git a/backend/pkg/flakeid/flakeid.go b/backend/pkg/flakeid/flakeid.go new file mode 100644 index 000000000..13e064896 --- /dev/null +++ b/backend/pkg/flakeid/flakeid.go @@ -0,0 +1,20 @@ +package flakeid + +const ( + SEQ_ID_SIZE = 8 + SHARD_ID_SIZE = 16 + TIMESTAMP_SIZE = 64 - SEQ_ID_SIZE - SHARD_ID_SHIFT + SEQ_ID_MAX = 1<> TIMESTAMP_SHIFT) +} diff --git a/backend/pkg/flakeid/flaker.go b/backend/pkg/flakeid/flaker.go new file mode 100644 index 000000000..5daba4feb --- /dev/null +++ b/backend/pkg/flakeid/flaker.go @@ -0,0 +1,47 @@ +package flakeid + +import ( + "errors" + "sync" +) + +type Flaker struct { + shardID uint16 + seqID uint8 + seqMutex *sync.Mutex +} + +func NewFlaker(shardID uint16) *Flaker { + return &Flaker{ + shardID: shardID, + seqID: 0, + seqMutex: &sync.Mutex{}, + } +} + +func (flaker *Flaker) nextSeqID() uint8 { + flaker.seqMutex.Lock() + defer flaker.seqMutex.Unlock() + seqID := flaker.seqID + if seqID == SEQ_ID_MAX { + flaker.seqID = 0 + } else { + flaker.seqID = seqID + 1 + } + return seqID +} + +func (flaker *Flaker) Compose(timestamp uint64) (uint64, error) { + if timestamp <= EPOCH { + return 0, errors.New("epoch is not in the past") + } + timestamp -= EPOCH + if timestamp > TIMESTAMP_MAX { + return 0, errors.New("epoch is too small") + } + return compose(timestamp, flaker.shardID, flaker.nextSeqID()), nil +} + +func (flaker *Flaker) ExtractTimestamp(id uint64) uint64 { + return extractTimestamp(id) + EPOCH +} diff --git a/backend/pkg/hashid/hashid.go b/backend/pkg/hashid/hashid.go new file mode 100644 index 000000000..1a33085ea --- /dev/null +++ b/backend/pkg/hashid/hashid.go @@ -0,0 +1,35 @@ +package hashid + +import ( + "encoding/hex" + "hash/fnv" + "strconv" + + "openreplay/backend/pkg/messages" +) + +func IssueID(projectID uint32, e *messages.IssueEvent) string { + hash := fnv.New128a() + hash.Write([]byte(e.Type)) + hash.Write([]byte(e.ContextString)) + //hash.Write([]byte(e.Context)) // More detailed that contextString (what about Data Redundancy?) + return strconv.FormatUint(uint64(projectID), 16) + hex.EncodeToString(hash.Sum(nil)) +} + + +func IOSCrashID(projectID uint32, crash *messages.IOSCrash) string { + hash := fnv.New128a() + hash.Write([]byte(crash.Name)) + hash.Write([]byte(crash.Reason)) + hash.Write([]byte(crash.Stacktrace)) + return strconv.FormatUint(uint64(projectID), 16) + hex.EncodeToString(hash.Sum(nil)) +} + +func WebErrorID(projectID uint32, errorEvent *messages.ErrorEvent) string { + hash := fnv.New128a() + hash.Write([]byte(errorEvent.Source)) + hash.Write([]byte(errorEvent.Name)) + hash.Write([]byte(errorEvent.Message)) + hash.Write([]byte(errorEvent.Payload)) + return strconv.FormatUint(uint64(projectID), 16) + hex.EncodeToString(hash.Sum(nil)) +} diff --git a/backend/pkg/intervals/intervals.go b/backend/pkg/intervals/intervals.go new file mode 100644 index 000000000..d7e6bfad5 --- /dev/null +++ b/backend/pkg/intervals/intervals.go @@ -0,0 +1,11 @@ +package intervals + +const EVENTS_COMMIT_INTERVAL = 1 * 60 * 1000 +const HEARTBEAT_INTERVAL = 2 * 60 * 1000 +const INTEGRATIONS_REQUEST_INTERVAL = 2 * 60 * 1000 +const EVENTS_PAGE_EVENT_TIMEOUT = 2 * 60 * 1000 +const EVENTS_INPUT_EVENT_TIMEOUT = 2 * 60 * 1000 +const EVENTS_PERFORMANCE_AGGREGATION_TIMEOUT = 2 * 60 * 1000 +const EVENTS_SESSION_END_TIMEOUT = HEARTBEAT_INTERVAL + 30 * 1000 +const EVENTS_SESSION_END_TIMEOUT_WITH_INTEGRATIONS = HEARTBEAT_INTERVAL + 3 * 60 * 1000 +const EVENTS_BACK_COMMIT_GAP = EVENTS_SESSION_END_TIMEOUT_WITH_INTEGRATIONS + 1*60*1000 diff --git a/backend/pkg/messages/batch.go b/backend/pkg/messages/batch.go new file mode 100644 index 000000000..97a3a58f1 --- /dev/null +++ b/backend/pkg/messages/batch.go @@ -0,0 +1,71 @@ +package messages + +import ( + "io" + "bytes" + + "github.com/pkg/errors" +) + +func ReadBatch(b []byte, callback func(Message)) error { + reader := bytes.NewReader(b) + var index uint64 + var timestamp int64 + for { + msg, err := ReadMessage(reader) + if err == io.EOF { + return nil + } else if err != nil { + return errors.Wrapf(err, "Batch Message decoding error on message with index %v", index) + } + isBatchMeta := false + switch m := msg.(type){ + case *BatchMeta: // Is not required to be present in batch since IOS doesn't have it (though we might change it) + if index != 0 { // Might be several 0-0 BatchMeta in a row without a error though + return errors.New("Batch Meta found at the end of the batch") + } + index = m.PageNo << 32 + m.FirstIndex // 2^32 is the maximum count of messages per page (ha-ha) + timestamp = m.Timestamp + isBatchMeta = true + // continue readLoop + case *Timestamp: + timestamp = int64(m.Timestamp) // TODO(?): replace timestamp type to int64 everywhere (including encoding part in tracker) + // No skipping here for making it easy to encode back the same sequence of message + // continue readLoop + } + msg.Meta().Index = index + msg.Meta().Timestamp = timestamp + callback(msg) + if !isBatchMeta { // Without that indexes will be unique anyway, though shifted by 1 because BatchMeta is not counted in tracker + index++ + } + } + return errors.New("Error of the codeflow. (Should return on EOF)") +} + +const AVG_MESSAGE_SIZE = 40 // TODO: calculate OR calculate dynamically +func WriteBatch(mList []Message) []byte { + batch := make([]byte, AVG_MESSAGE_SIZE * len(mList)) + p := 0 + for _, msg := range mList { + msgBytes := msg.Encode() + if len(batch) < p + len(msgBytes) { + newBatch := make([]byte, 2*len(batch) + len(msgBytes)) + copy(newBatch, batch) + batch = newBatch + } + copy(batch[p:], msgBytes) + p += len(msgBytes) + } + return batch[:p] +} + +func RewriteBatch(b []byte, rewrite func(Message) Message) ([]byte, error) { + mList := make([]Message, 0, len(b)/AVG_MESSAGE_SIZE) + if err := ReadBatch(b, func(m Message) { + mList = append(mList, rewrite(m)) + }); err != nil { + return nil, err + } + return WriteBatch(mList), nil +} \ No newline at end of file diff --git a/backend/pkg/messages/facade.go b/backend/pkg/messages/facade.go new file mode 100644 index 000000000..91d896d19 --- /dev/null +++ b/backend/pkg/messages/facade.go @@ -0,0 +1,41 @@ +package messages + +import ( + "bytes" + //"io" +) + +func Encode(msg Message) []byte { + return msg.Encode() +} + +// +// func EncodeList(msgs []Message) []byte { + +// } +// + +// func Decode(b []byte) (Message, error) { +// return ReadMessage(bytes.NewReader(b)) +// } + +// func DecodeEach(b []byte, callback func(Message)) error { +// var err error +// reader := bytes.NewReader(b) +// for { +// msg, err := ReadMessage(reader) +// if err != nil { +// break +// } +// callback(msg) +// } +// if err == io.EOF { +// return nil +// } +// return err +// } + +func GetMessageTypeID(b []byte) (uint64, error) { + reader := bytes.NewReader(b) + return ReadUint(reader) +} diff --git a/backend/pkg/messages/filters.go b/backend/pkg/messages/filters.go new file mode 100644 index 000000000..1d72b41f8 --- /dev/null +++ b/backend/pkg/messages/filters.go @@ -0,0 +1,10 @@ +package messages + + +func IsReplayerType(id uint64) bool { + return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 22 == id || 37 == id || 38 == id || 39 == id || 40 == id || 41 == id || 44 == id || 45 == id || 46 == id || 47 == id || 48 == id || 49 == id || 54 == id || 55 == id || 59 == id || 90 == id || 93 == id || 100 == id || 102 == id || 103 == id || 105 == id +} + +func IsIOSType(id uint64) bool { + return 90 == id || 91 == id || 92 == id || 93 == id || 94 == id || 95 == id || 96 == id || 97 == id || 98 == id || 99 == id || 100 == id || 101 == id || 102 == id || 103 == id || 104 == id || 105 == id || 110 == id || 111 == id +} diff --git a/backend/pkg/messages/messages.go b/backend/pkg/messages/messages.go new file mode 100644 index 000000000..1677af87c --- /dev/null +++ b/backend/pkg/messages/messages.go @@ -0,0 +1,1506 @@ +// Auto-generated, do not edit +package messages + +type Message interface { + Encode() []byte + Meta() *meta +} + +type meta struct { + Timestamp int64 + Index uint64 + TypeID uint64 +} + +// Might also implement Encode() here (?) +func (m *meta) Meta() *meta { + return m +} + + +type BatchMeta struct { + *meta + PageNo uint64 +FirstIndex uint64 +Timestamp int64 +} +func (msg *BatchMeta) Encode() []byte{ + buf := make([]byte, 31 ) + buf[0] = 80 + p := 1 + p = WriteUint(msg.PageNo, buf, p) +p = WriteUint(msg.FirstIndex, buf, p) +p = WriteInt(msg.Timestamp, buf, p) + return buf[:p] +} + +type Timestamp struct { + *meta + Timestamp uint64 +} +func (msg *Timestamp) Encode() []byte{ + buf := make([]byte, 11 ) + buf[0] = 0 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) + return buf[:p] +} + +type SessionStart struct { + *meta + Timestamp uint64 +ProjectID uint64 +TrackerVersion string +RevID string +UserUUID string +UserAgent string +UserOS string +UserOSVersion string +UserBrowser string +UserBrowserVersion string +UserDevice string +UserDeviceType string +UserDeviceMemorySize uint64 +UserDeviceHeapSize uint64 +UserCountry string +} +func (msg *SessionStart) Encode() []byte{ + buf := make([]byte, 151 + len(msg.TrackerVersion)+ len(msg.RevID)+ len(msg.UserUUID)+ len(msg.UserAgent)+ len(msg.UserOS)+ len(msg.UserOSVersion)+ len(msg.UserBrowser)+ len(msg.UserBrowserVersion)+ len(msg.UserDevice)+ len(msg.UserDeviceType)+ len(msg.UserCountry)) + buf[0] = 1 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.ProjectID, buf, p) +p = WriteString(msg.TrackerVersion, buf, p) +p = WriteString(msg.RevID, buf, p) +p = WriteString(msg.UserUUID, buf, p) +p = WriteString(msg.UserAgent, buf, p) +p = WriteString(msg.UserOS, buf, p) +p = WriteString(msg.UserOSVersion, buf, p) +p = WriteString(msg.UserBrowser, buf, p) +p = WriteString(msg.UserBrowserVersion, buf, p) +p = WriteString(msg.UserDevice, buf, p) +p = WriteString(msg.UserDeviceType, buf, p) +p = WriteUint(msg.UserDeviceMemorySize, buf, p) +p = WriteUint(msg.UserDeviceHeapSize, buf, p) +p = WriteString(msg.UserCountry, buf, p) + return buf[:p] +} + +type SessionEnd struct { + *meta + Timestamp uint64 +} +func (msg *SessionEnd) Encode() []byte{ + buf := make([]byte, 11 ) + buf[0] = 3 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) + return buf[:p] +} + +type SetPageLocation struct { + *meta + URL string +Referrer string +NavigationStart uint64 +} +func (msg *SetPageLocation) Encode() []byte{ + buf := make([]byte, 31 + len(msg.URL)+ len(msg.Referrer)) + buf[0] = 4 + p := 1 + p = WriteString(msg.URL, buf, p) +p = WriteString(msg.Referrer, buf, p) +p = WriteUint(msg.NavigationStart, buf, p) + return buf[:p] +} + +type SetViewportSize struct { + *meta + Width uint64 +Height uint64 +} +func (msg *SetViewportSize) Encode() []byte{ + buf := make([]byte, 21 ) + buf[0] = 5 + p := 1 + p = WriteUint(msg.Width, buf, p) +p = WriteUint(msg.Height, buf, p) + return buf[:p] +} + +type SetViewportScroll struct { + *meta + X int64 +Y int64 +} +func (msg *SetViewportScroll) Encode() []byte{ + buf := make([]byte, 21 ) + buf[0] = 6 + p := 1 + p = WriteInt(msg.X, buf, p) +p = WriteInt(msg.Y, buf, p) + return buf[:p] +} + +type CreateDocument struct { + *meta + +} +func (msg *CreateDocument) Encode() []byte{ + buf := make([]byte, 1 ) + buf[0] = 7 + p := 1 + + return buf[:p] +} + +type CreateElementNode struct { + *meta + ID uint64 +ParentID uint64 +index uint64 +Tag string +SVG bool +} +func (msg *CreateElementNode) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Tag)) + buf[0] = 8 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteUint(msg.ParentID, buf, p) +p = WriteUint(msg.index, buf, p) +p = WriteString(msg.Tag, buf, p) +p = WriteBoolean(msg.SVG, buf, p) + return buf[:p] +} + +type CreateTextNode struct { + *meta + ID uint64 +ParentID uint64 +Index uint64 +} +func (msg *CreateTextNode) Encode() []byte{ + buf := make([]byte, 31 ) + buf[0] = 9 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteUint(msg.ParentID, buf, p) +p = WriteUint(msg.Index, buf, p) + return buf[:p] +} + +type MoveNode struct { + *meta + ID uint64 +ParentID uint64 +Index uint64 +} +func (msg *MoveNode) Encode() []byte{ + buf := make([]byte, 31 ) + buf[0] = 10 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteUint(msg.ParentID, buf, p) +p = WriteUint(msg.Index, buf, p) + return buf[:p] +} + +type RemoveNode struct { + *meta + ID uint64 +} +func (msg *RemoveNode) Encode() []byte{ + buf := make([]byte, 11 ) + buf[0] = 11 + p := 1 + p = WriteUint(msg.ID, buf, p) + return buf[:p] +} + +type SetNodeAttribute struct { + *meta + ID uint64 +Name string +Value string +} +func (msg *SetNodeAttribute) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Name)+ len(msg.Value)) + buf[0] = 12 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type RemoveNodeAttribute struct { + *meta + ID uint64 +Name string +} +func (msg *RemoveNodeAttribute) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Name)) + buf[0] = 13 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Name, buf, p) + return buf[:p] +} + +type SetNodeData struct { + *meta + ID uint64 +Data string +} +func (msg *SetNodeData) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Data)) + buf[0] = 14 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Data, buf, p) + return buf[:p] +} + +type SetCSSData struct { + *meta + ID uint64 +Data string +} +func (msg *SetCSSData) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Data)) + buf[0] = 15 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Data, buf, p) + return buf[:p] +} + +type SetNodeScroll struct { + *meta + ID uint64 +X int64 +Y int64 +} +func (msg *SetNodeScroll) Encode() []byte{ + buf := make([]byte, 31 ) + buf[0] = 16 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteInt(msg.X, buf, p) +p = WriteInt(msg.Y, buf, p) + return buf[:p] +} + +type SetInputTarget struct { + *meta + ID uint64 +Label string +} +func (msg *SetInputTarget) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Label)) + buf[0] = 17 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Label, buf, p) + return buf[:p] +} + +type SetInputValue struct { + *meta + ID uint64 +Value string +Mask int64 +} +func (msg *SetInputValue) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Value)) + buf[0] = 18 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Value, buf, p) +p = WriteInt(msg.Mask, buf, p) + return buf[:p] +} + +type SetInputChecked struct { + *meta + ID uint64 +Checked bool +} +func (msg *SetInputChecked) Encode() []byte{ + buf := make([]byte, 21 ) + buf[0] = 19 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteBoolean(msg.Checked, buf, p) + return buf[:p] +} + +type MouseMove struct { + *meta + X uint64 +Y uint64 +} +func (msg *MouseMove) Encode() []byte{ + buf := make([]byte, 21 ) + buf[0] = 20 + p := 1 + p = WriteUint(msg.X, buf, p) +p = WriteUint(msg.Y, buf, p) + return buf[:p] +} + +type MouseClick struct { + *meta + ID uint64 +HesitationTime uint64 +Label string +} +func (msg *MouseClick) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Label)) + buf[0] = 21 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteUint(msg.HesitationTime, buf, p) +p = WriteString(msg.Label, buf, p) + return buf[:p] +} + +type ConsoleLog struct { + *meta + Level string +Value string +} +func (msg *ConsoleLog) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Level)+ len(msg.Value)) + buf[0] = 22 + p := 1 + p = WriteString(msg.Level, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type PageLoadTiming struct { + *meta + RequestStart uint64 +ResponseStart uint64 +ResponseEnd uint64 +DomContentLoadedEventStart uint64 +DomContentLoadedEventEnd uint64 +LoadEventStart uint64 +LoadEventEnd uint64 +FirstPaint uint64 +FirstContentfulPaint uint64 +} +func (msg *PageLoadTiming) Encode() []byte{ + buf := make([]byte, 91 ) + buf[0] = 23 + p := 1 + p = WriteUint(msg.RequestStart, buf, p) +p = WriteUint(msg.ResponseStart, buf, p) +p = WriteUint(msg.ResponseEnd, buf, p) +p = WriteUint(msg.DomContentLoadedEventStart, buf, p) +p = WriteUint(msg.DomContentLoadedEventEnd, buf, p) +p = WriteUint(msg.LoadEventStart, buf, p) +p = WriteUint(msg.LoadEventEnd, buf, p) +p = WriteUint(msg.FirstPaint, buf, p) +p = WriteUint(msg.FirstContentfulPaint, buf, p) + return buf[:p] +} + +type PageRenderTiming struct { + *meta + SpeedIndex uint64 +VisuallyComplete uint64 +TimeToInteractive uint64 +} +func (msg *PageRenderTiming) Encode() []byte{ + buf := make([]byte, 31 ) + buf[0] = 24 + p := 1 + p = WriteUint(msg.SpeedIndex, buf, p) +p = WriteUint(msg.VisuallyComplete, buf, p) +p = WriteUint(msg.TimeToInteractive, buf, p) + return buf[:p] +} + +type JSException struct { + *meta + Name string +Message string +Payload string +} +func (msg *JSException) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Name)+ len(msg.Message)+ len(msg.Payload)) + buf[0] = 25 + p := 1 + p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Message, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type RawErrorEvent struct { + *meta + Timestamp uint64 +Source string +Name string +Message string +Payload string +} +func (msg *RawErrorEvent) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Source)+ len(msg.Name)+ len(msg.Message)+ len(msg.Payload)) + buf[0] = 26 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Source, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Message, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type RawCustomEvent struct { + *meta + Name string +Payload string +} +func (msg *RawCustomEvent) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Name)+ len(msg.Payload)) + buf[0] = 27 + p := 1 + p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type UserID struct { + *meta + ID string +} +func (msg *UserID) Encode() []byte{ + buf := make([]byte, 11 + len(msg.ID)) + buf[0] = 28 + p := 1 + p = WriteString(msg.ID, buf, p) + return buf[:p] +} + +type UserAnonymousID struct { + *meta + ID string +} +func (msg *UserAnonymousID) Encode() []byte{ + buf := make([]byte, 11 + len(msg.ID)) + buf[0] = 29 + p := 1 + p = WriteString(msg.ID, buf, p) + return buf[:p] +} + +type Metadata struct { + *meta + Key string +Value string +} +func (msg *Metadata) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Key)+ len(msg.Value)) + buf[0] = 30 + p := 1 + p = WriteString(msg.Key, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type PageEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +URL string +Referrer string +Loaded bool +RequestStart uint64 +ResponseStart uint64 +ResponseEnd uint64 +DomContentLoadedEventStart uint64 +DomContentLoadedEventEnd uint64 +LoadEventStart uint64 +LoadEventEnd uint64 +FirstPaint uint64 +FirstContentfulPaint uint64 +SpeedIndex uint64 +VisuallyComplete uint64 +TimeToInteractive uint64 +} +func (msg *PageEvent) Encode() []byte{ + buf := make([]byte, 171 + len(msg.URL)+ len(msg.Referrer)) + buf[0] = 31 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.URL, buf, p) +p = WriteString(msg.Referrer, buf, p) +p = WriteBoolean(msg.Loaded, buf, p) +p = WriteUint(msg.RequestStart, buf, p) +p = WriteUint(msg.ResponseStart, buf, p) +p = WriteUint(msg.ResponseEnd, buf, p) +p = WriteUint(msg.DomContentLoadedEventStart, buf, p) +p = WriteUint(msg.DomContentLoadedEventEnd, buf, p) +p = WriteUint(msg.LoadEventStart, buf, p) +p = WriteUint(msg.LoadEventEnd, buf, p) +p = WriteUint(msg.FirstPaint, buf, p) +p = WriteUint(msg.FirstContentfulPaint, buf, p) +p = WriteUint(msg.SpeedIndex, buf, p) +p = WriteUint(msg.VisuallyComplete, buf, p) +p = WriteUint(msg.TimeToInteractive, buf, p) + return buf[:p] +} + +type InputEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Value string +ValueMasked bool +Label string +} +func (msg *InputEvent) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Value)+ len(msg.Label)) + buf[0] = 32 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Value, buf, p) +p = WriteBoolean(msg.ValueMasked, buf, p) +p = WriteString(msg.Label, buf, p) + return buf[:p] +} + +type ClickEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +HesitationTime uint64 +Label string +} +func (msg *ClickEvent) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Label)) + buf[0] = 33 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.HesitationTime, buf, p) +p = WriteString(msg.Label, buf, p) + return buf[:p] +} + +type ErrorEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Source string +Name string +Message string +Payload string +} +func (msg *ErrorEvent) Encode() []byte{ + buf := make([]byte, 61 + len(msg.Source)+ len(msg.Name)+ len(msg.Message)+ len(msg.Payload)) + buf[0] = 34 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Source, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Message, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type ResourceEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Duration uint64 +TTFB uint64 +HeaderSize uint64 +EncodedBodySize uint64 +DecodedBodySize uint64 +URL string +Type string +Success bool +Method string +Status uint64 +} +func (msg *ResourceEvent) Encode() []byte{ + buf := make([]byte, 121 + len(msg.URL)+ len(msg.Type)+ len(msg.Method)) + buf[0] = 35 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Duration, buf, p) +p = WriteUint(msg.TTFB, buf, p) +p = WriteUint(msg.HeaderSize, buf, p) +p = WriteUint(msg.EncodedBodySize, buf, p) +p = WriteUint(msg.DecodedBodySize, buf, p) +p = WriteString(msg.URL, buf, p) +p = WriteString(msg.Type, buf, p) +p = WriteBoolean(msg.Success, buf, p) +p = WriteString(msg.Method, buf, p) +p = WriteUint(msg.Status, buf, p) + return buf[:p] +} + +type CustomEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Name string +Payload string +} +func (msg *CustomEvent) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Name)+ len(msg.Payload)) + buf[0] = 36 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type CSSInsertRule struct { + *meta + ID uint64 +Rule string +Index uint64 +} +func (msg *CSSInsertRule) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Rule)) + buf[0] = 37 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Rule, buf, p) +p = WriteUint(msg.Index, buf, p) + return buf[:p] +} + +type CSSDeleteRule struct { + *meta + ID uint64 +Index uint64 +} +func (msg *CSSDeleteRule) Encode() []byte{ + buf := make([]byte, 21 ) + buf[0] = 38 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteUint(msg.Index, buf, p) + return buf[:p] +} + +type Fetch struct { + *meta + Method string +URL string +Request string +Response string +Status uint64 +Timestamp uint64 +Duration uint64 +} +func (msg *Fetch) Encode() []byte{ + buf := make([]byte, 71 + len(msg.Method)+ len(msg.URL)+ len(msg.Request)+ len(msg.Response)) + buf[0] = 39 + p := 1 + p = WriteString(msg.Method, buf, p) +p = WriteString(msg.URL, buf, p) +p = WriteString(msg.Request, buf, p) +p = WriteString(msg.Response, buf, p) +p = WriteUint(msg.Status, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Duration, buf, p) + return buf[:p] +} + +type Profiler struct { + *meta + Name string +Duration uint64 +Args string +Result string +} +func (msg *Profiler) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Name)+ len(msg.Args)+ len(msg.Result)) + buf[0] = 40 + p := 1 + p = WriteString(msg.Name, buf, p) +p = WriteUint(msg.Duration, buf, p) +p = WriteString(msg.Args, buf, p) +p = WriteString(msg.Result, buf, p) + return buf[:p] +} + +type OTable struct { + *meta + Key string +Value string +} +func (msg *OTable) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Key)+ len(msg.Value)) + buf[0] = 41 + p := 1 + p = WriteString(msg.Key, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type StateAction struct { + *meta + Type string +} +func (msg *StateAction) Encode() []byte{ + buf := make([]byte, 11 + len(msg.Type)) + buf[0] = 42 + p := 1 + p = WriteString(msg.Type, buf, p) + return buf[:p] +} + +type StateActionEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Type string +} +func (msg *StateActionEvent) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Type)) + buf[0] = 43 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Type, buf, p) + return buf[:p] +} + +type Redux struct { + *meta + Action string +State string +Duration uint64 +} +func (msg *Redux) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Action)+ len(msg.State)) + buf[0] = 44 + p := 1 + p = WriteString(msg.Action, buf, p) +p = WriteString(msg.State, buf, p) +p = WriteUint(msg.Duration, buf, p) + return buf[:p] +} + +type Vuex struct { + *meta + Mutation string +State string +} +func (msg *Vuex) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Mutation)+ len(msg.State)) + buf[0] = 45 + p := 1 + p = WriteString(msg.Mutation, buf, p) +p = WriteString(msg.State, buf, p) + return buf[:p] +} + +type MobX struct { + *meta + Type string +Payload string +} +func (msg *MobX) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Type)+ len(msg.Payload)) + buf[0] = 46 + p := 1 + p = WriteString(msg.Type, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type NgRx struct { + *meta + Action string +State string +Duration uint64 +} +func (msg *NgRx) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Action)+ len(msg.State)) + buf[0] = 47 + p := 1 + p = WriteString(msg.Action, buf, p) +p = WriteString(msg.State, buf, p) +p = WriteUint(msg.Duration, buf, p) + return buf[:p] +} + +type GraphQL struct { + *meta + OperationKind string +OperationName string +Variables string +Response string +} +func (msg *GraphQL) Encode() []byte{ + buf := make([]byte, 41 + len(msg.OperationKind)+ len(msg.OperationName)+ len(msg.Variables)+ len(msg.Response)) + buf[0] = 48 + p := 1 + p = WriteString(msg.OperationKind, buf, p) +p = WriteString(msg.OperationName, buf, p) +p = WriteString(msg.Variables, buf, p) +p = WriteString(msg.Response, buf, p) + return buf[:p] +} + +type PerformanceTrack struct { + *meta + Frames int64 +Ticks int64 +TotalJSHeapSize uint64 +UsedJSHeapSize uint64 +} +func (msg *PerformanceTrack) Encode() []byte{ + buf := make([]byte, 41 ) + buf[0] = 49 + p := 1 + p = WriteInt(msg.Frames, buf, p) +p = WriteInt(msg.Ticks, buf, p) +p = WriteUint(msg.TotalJSHeapSize, buf, p) +p = WriteUint(msg.UsedJSHeapSize, buf, p) + return buf[:p] +} + +type GraphQLEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Name string +} +func (msg *GraphQLEvent) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Name)) + buf[0] = 50 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Name, buf, p) + return buf[:p] +} + +type DOMDrop struct { + *meta + Timestamp uint64 +} +func (msg *DOMDrop) Encode() []byte{ + buf := make([]byte, 11 ) + buf[0] = 52 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) + return buf[:p] +} + +type ResourceTiming struct { + *meta + Timestamp uint64 +Duration uint64 +TTFB uint64 +HeaderSize uint64 +EncodedBodySize uint64 +DecodedBodySize uint64 +URL string +Initiator string +} +func (msg *ResourceTiming) Encode() []byte{ + buf := make([]byte, 81 + len(msg.URL)+ len(msg.Initiator)) + buf[0] = 53 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Duration, buf, p) +p = WriteUint(msg.TTFB, buf, p) +p = WriteUint(msg.HeaderSize, buf, p) +p = WriteUint(msg.EncodedBodySize, buf, p) +p = WriteUint(msg.DecodedBodySize, buf, p) +p = WriteString(msg.URL, buf, p) +p = WriteString(msg.Initiator, buf, p) + return buf[:p] +} + +type ConnectionInformation struct { + *meta + Downlink uint64 +Type string +} +func (msg *ConnectionInformation) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Type)) + buf[0] = 54 + p := 1 + p = WriteUint(msg.Downlink, buf, p) +p = WriteString(msg.Type, buf, p) + return buf[:p] +} + +type SetPageVisibility struct { + *meta + hidden bool +} +func (msg *SetPageVisibility) Encode() []byte{ + buf := make([]byte, 11 ) + buf[0] = 55 + p := 1 + p = WriteBoolean(msg.hidden, buf, p) + return buf[:p] +} + +type PerformanceTrackAggr struct { + *meta + TimestampStart uint64 +TimestampEnd uint64 +MinFPS uint64 +AvgFPS uint64 +MaxFPS uint64 +MinCPU uint64 +AvgCPU uint64 +MaxCPU uint64 +MinTotalJSHeapSize uint64 +AvgTotalJSHeapSize uint64 +MaxTotalJSHeapSize uint64 +MinUsedJSHeapSize uint64 +AvgUsedJSHeapSize uint64 +MaxUsedJSHeapSize uint64 +} +func (msg *PerformanceTrackAggr) Encode() []byte{ + buf := make([]byte, 141 ) + buf[0] = 56 + p := 1 + p = WriteUint(msg.TimestampStart, buf, p) +p = WriteUint(msg.TimestampEnd, buf, p) +p = WriteUint(msg.MinFPS, buf, p) +p = WriteUint(msg.AvgFPS, buf, p) +p = WriteUint(msg.MaxFPS, buf, p) +p = WriteUint(msg.MinCPU, buf, p) +p = WriteUint(msg.AvgCPU, buf, p) +p = WriteUint(msg.MaxCPU, buf, p) +p = WriteUint(msg.MinTotalJSHeapSize, buf, p) +p = WriteUint(msg.AvgTotalJSHeapSize, buf, p) +p = WriteUint(msg.MaxTotalJSHeapSize, buf, p) +p = WriteUint(msg.MinUsedJSHeapSize, buf, p) +p = WriteUint(msg.AvgUsedJSHeapSize, buf, p) +p = WriteUint(msg.MaxUsedJSHeapSize, buf, p) + return buf[:p] +} + +type LongTask struct { + *meta + Timestamp uint64 +Duration uint64 +Context uint64 +ContainerType uint64 +ContainerSrc string +ContainerId string +ContainerName string +} +func (msg *LongTask) Encode() []byte{ + buf := make([]byte, 71 + len(msg.ContainerSrc)+ len(msg.ContainerId)+ len(msg.ContainerName)) + buf[0] = 59 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Duration, buf, p) +p = WriteUint(msg.Context, buf, p) +p = WriteUint(msg.ContainerType, buf, p) +p = WriteString(msg.ContainerSrc, buf, p) +p = WriteString(msg.ContainerId, buf, p) +p = WriteString(msg.ContainerName, buf, p) + return buf[:p] +} + +type SetNodeAttributeURLBased struct { + *meta + ID uint64 +Name string +Value string +BaseURL string +} +func (msg *SetNodeAttributeURLBased) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Name)+ len(msg.Value)+ len(msg.BaseURL)) + buf[0] = 60 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Value, buf, p) +p = WriteString(msg.BaseURL, buf, p) + return buf[:p] +} + +type SetCSSDataURLBased struct { + *meta + ID uint64 +Data string +BaseURL string +} +func (msg *SetCSSDataURLBased) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Data)+ len(msg.BaseURL)) + buf[0] = 61 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Data, buf, p) +p = WriteString(msg.BaseURL, buf, p) + return buf[:p] +} + +type IssueEvent struct { + *meta + MessageID uint64 +Timestamp uint64 +Type string +ContextString string +Context string +Payload string +} +func (msg *IssueEvent) Encode() []byte{ + buf := make([]byte, 61 + len(msg.Type)+ len(msg.ContextString)+ len(msg.Context)+ len(msg.Payload)) + buf[0] = 62 + p := 1 + p = WriteUint(msg.MessageID, buf, p) +p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Type, buf, p) +p = WriteString(msg.ContextString, buf, p) +p = WriteString(msg.Context, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type TechnicalInfo struct { + *meta + Type string +Value string +} +func (msg *TechnicalInfo) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Type)+ len(msg.Value)) + buf[0] = 63 + p := 1 + p = WriteString(msg.Type, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type CustomIssue struct { + *meta + Name string +Payload string +} +func (msg *CustomIssue) Encode() []byte{ + buf := make([]byte, 21 + len(msg.Name)+ len(msg.Payload)) + buf[0] = 64 + p := 1 + p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type PageClose struct { + *meta + +} +func (msg *PageClose) Encode() []byte{ + buf := make([]byte, 1 ) + buf[0] = 65 + p := 1 + + return buf[:p] +} + +type AssetCache struct { + *meta + URL string +} +func (msg *AssetCache) Encode() []byte{ + buf := make([]byte, 11 + len(msg.URL)) + buf[0] = 66 + p := 1 + p = WriteString(msg.URL, buf, p) + return buf[:p] +} + +type CSSInsertRuleURLBased struct { + *meta + ID uint64 +Rule string +Index uint64 +BaseURL string +} +func (msg *CSSInsertRuleURLBased) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Rule)+ len(msg.BaseURL)) + buf[0] = 67 + p := 1 + p = WriteUint(msg.ID, buf, p) +p = WriteString(msg.Rule, buf, p) +p = WriteUint(msg.Index, buf, p) +p = WriteString(msg.BaseURL, buf, p) + return buf[:p] +} + +type IOSSessionStart struct { + *meta + Timestamp uint64 +ProjectID uint64 +TrackerVersion string +RevID string +UserUUID string +UserOS string +UserOSVersion string +UserDevice string +UserDeviceType string +UserCountry string +} +func (msg *IOSSessionStart) Encode() []byte{ + buf := make([]byte, 101 + len(msg.TrackerVersion)+ len(msg.RevID)+ len(msg.UserUUID)+ len(msg.UserOS)+ len(msg.UserOSVersion)+ len(msg.UserDevice)+ len(msg.UserDeviceType)+ len(msg.UserCountry)) + buf[0] = 90 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.ProjectID, buf, p) +p = WriteString(msg.TrackerVersion, buf, p) +p = WriteString(msg.RevID, buf, p) +p = WriteString(msg.UserUUID, buf, p) +p = WriteString(msg.UserOS, buf, p) +p = WriteString(msg.UserOSVersion, buf, p) +p = WriteString(msg.UserDevice, buf, p) +p = WriteString(msg.UserDeviceType, buf, p) +p = WriteString(msg.UserCountry, buf, p) + return buf[:p] +} + +type IOSSessionEnd struct { + *meta + Timestamp uint64 +} +func (msg *IOSSessionEnd) Encode() []byte{ + buf := make([]byte, 11 ) + buf[0] = 91 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) + return buf[:p] +} + +type IOSMetadata struct { + *meta + Timestamp uint64 +Length uint64 +Key string +Value string +} +func (msg *IOSMetadata) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Key)+ len(msg.Value)) + buf[0] = 92 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Key, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type IOSCustomEvent struct { + *meta + Timestamp uint64 +Length uint64 +Name string +Payload string +} +func (msg *IOSCustomEvent) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Name)+ len(msg.Payload)) + buf[0] = 93 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + +type IOSUserID struct { + *meta + Timestamp uint64 +Length uint64 +Value string +} +func (msg *IOSUserID) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Value)) + buf[0] = 94 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type IOSUserAnonymousID struct { + *meta + Timestamp uint64 +Length uint64 +Value string +} +func (msg *IOSUserAnonymousID) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Value)) + buf[0] = 95 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Value, buf, p) + return buf[:p] +} + +type IOSScreenChanges struct { + *meta + Timestamp uint64 +SkipData []byte +} +func (msg *IOSScreenChanges) Encode() []byte{ + buf := make([]byte, 21 + len(msg.SkipData)) + buf[0] = 96 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteData(msg.SkipData, buf, p) + return buf[:p] +} + +type IOSCrash struct { + *meta + Timestamp uint64 +Length uint64 +Name string +Reason string +Stacktrace string +} +func (msg *IOSCrash) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Name)+ len(msg.Reason)+ len(msg.Stacktrace)) + buf[0] = 97 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteString(msg.Reason, buf, p) +p = WriteString(msg.Stacktrace, buf, p) + return buf[:p] +} + +type IOSScreenEnter struct { + *meta + Timestamp uint64 +Length uint64 +Title string +ViewName string +} +func (msg *IOSScreenEnter) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Title)+ len(msg.ViewName)) + buf[0] = 98 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Title, buf, p) +p = WriteString(msg.ViewName, buf, p) + return buf[:p] +} + +type IOSScreenLeave struct { + *meta + Timestamp uint64 +Length uint64 +Title string +ViewName string +} +func (msg *IOSScreenLeave) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Title)+ len(msg.ViewName)) + buf[0] = 99 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Title, buf, p) +p = WriteString(msg.ViewName, buf, p) + return buf[:p] +} + +type IOSClickEvent struct { + *meta + Timestamp uint64 +Length uint64 +Label string +X uint64 +Y uint64 +} +func (msg *IOSClickEvent) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Label)) + buf[0] = 100 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Label, buf, p) +p = WriteUint(msg.X, buf, p) +p = WriteUint(msg.Y, buf, p) + return buf[:p] +} + +type IOSInputEvent struct { + *meta + Timestamp uint64 +Length uint64 +Value string +ValueMasked bool +Label string +} +func (msg *IOSInputEvent) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Value)+ len(msg.Label)) + buf[0] = 101 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Value, buf, p) +p = WriteBoolean(msg.ValueMasked, buf, p) +p = WriteString(msg.Label, buf, p) + return buf[:p] +} + +type IOSPerformanceEvent struct { + *meta + Timestamp uint64 +Length uint64 +Name string +Value uint64 +} +func (msg *IOSPerformanceEvent) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Name)) + buf[0] = 102 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Name, buf, p) +p = WriteUint(msg.Value, buf, p) + return buf[:p] +} + +type IOSLog struct { + *meta + Timestamp uint64 +Length uint64 +Severity string +Content string +} +func (msg *IOSLog) Encode() []byte{ + buf := make([]byte, 41 + len(msg.Severity)+ len(msg.Content)) + buf[0] = 103 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Severity, buf, p) +p = WriteString(msg.Content, buf, p) + return buf[:p] +} + +type IOSInternalError struct { + *meta + Timestamp uint64 +Length uint64 +Content string +} +func (msg *IOSInternalError) Encode() []byte{ + buf := make([]byte, 31 + len(msg.Content)) + buf[0] = 104 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteString(msg.Content, buf, p) + return buf[:p] +} + +type IOSNetworkCall struct { + *meta + Timestamp uint64 +Length uint64 +Duration uint64 +Headers string +Body string +URL string +Success bool +Method string +Status uint64 +} +func (msg *IOSNetworkCall) Encode() []byte{ + buf := make([]byte, 91 + len(msg.Headers)+ len(msg.Body)+ len(msg.URL)+ len(msg.Method)) + buf[0] = 105 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteUint(msg.Length, buf, p) +p = WriteUint(msg.Duration, buf, p) +p = WriteString(msg.Headers, buf, p) +p = WriteString(msg.Body, buf, p) +p = WriteString(msg.URL, buf, p) +p = WriteBoolean(msg.Success, buf, p) +p = WriteString(msg.Method, buf, p) +p = WriteUint(msg.Status, buf, p) + return buf[:p] +} + +type IOSPerformanceAggregated struct { + *meta + TimestampStart uint64 +TimestampEnd uint64 +MinFPS uint64 +AvgFPS uint64 +MaxFPS uint64 +MinCPU uint64 +AvgCPU uint64 +MaxCPU uint64 +MinMemory uint64 +AvgMemory uint64 +MaxMemory uint64 +MinBattery uint64 +AvgBattery uint64 +MaxBattery uint64 +} +func (msg *IOSPerformanceAggregated) Encode() []byte{ + buf := make([]byte, 141 ) + buf[0] = 110 + p := 1 + p = WriteUint(msg.TimestampStart, buf, p) +p = WriteUint(msg.TimestampEnd, buf, p) +p = WriteUint(msg.MinFPS, buf, p) +p = WriteUint(msg.AvgFPS, buf, p) +p = WriteUint(msg.MaxFPS, buf, p) +p = WriteUint(msg.MinCPU, buf, p) +p = WriteUint(msg.AvgCPU, buf, p) +p = WriteUint(msg.MaxCPU, buf, p) +p = WriteUint(msg.MinMemory, buf, p) +p = WriteUint(msg.AvgMemory, buf, p) +p = WriteUint(msg.MaxMemory, buf, p) +p = WriteUint(msg.MinBattery, buf, p) +p = WriteUint(msg.AvgBattery, buf, p) +p = WriteUint(msg.MaxBattery, buf, p) + return buf[:p] +} + +type IOSIssueEvent struct { + *meta + Timestamp uint64 +Type string +ContextString string +Context string +Payload string +} +func (msg *IOSIssueEvent) Encode() []byte{ + buf := make([]byte, 51 + len(msg.Type)+ len(msg.ContextString)+ len(msg.Context)+ len(msg.Payload)) + buf[0] = 111 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) +p = WriteString(msg.Type, buf, p) +p = WriteString(msg.ContextString, buf, p) +p = WriteString(msg.Context, buf, p) +p = WriteString(msg.Payload, buf, p) + return buf[:p] +} + diff --git a/backend/pkg/messages/performance/performance.go b/backend/pkg/messages/performance/performance.go new file mode 100644 index 000000000..4cfb28045 --- /dev/null +++ b/backend/pkg/messages/performance/performance.go @@ -0,0 +1,33 @@ +package performance + +import ( + "math" +) + + +func TimeDiff(t1 uint64, t2 uint64) uint64 { + if t1 < t2 { + return 0 + } + return t1 - t2 +} + +func FrameRate(frames int64, dt uint64) float64 { + return float64(frames) * 1000 / float64(dt) +} + +func TickRate(ticks int64, dt uint64) float64 { + tickRate := float64(ticks) * 30 / float64(dt) + if tickRate > 1 { + tickRate = 1 + } + return tickRate +} + +func CPURateFromTickRate(tickRate float64) uint64 { + return 100 - uint64(math.Round(tickRate*100)) +} + +func CPURate(ticks int64, dt uint64) uint64 { + return CPURateFromTickRate(TickRate(ticks, dt)) +} \ No newline at end of file diff --git a/backend/pkg/messages/primitives.go b/backend/pkg/messages/primitives.go new file mode 100644 index 000000000..0c938d2b2 --- /dev/null +++ b/backend/pkg/messages/primitives.go @@ -0,0 +1,155 @@ +package messages + +import ( + "errors" + "io" + "encoding/json" + "log" +) + +func ReadByte(reader io.Reader) (byte, error) { + p := make([]byte, 1) + _, err := io.ReadFull(reader, p) + if err != nil { + return 0, err + } + return p[0], nil +} + +// func SkipBytes(reader io.ReadSeeker) error { +// n, err := ReadUint(reader) +// if err != nil { +// return err +// } +// _, err = reader.Seek(n, io.SeekCurrent); +// return err +// } + +func ReadData(reader io.Reader) ([]byte, error) { + n, err := ReadUint(reader) + if err != nil { + return nil, err + } + p := make([]byte, n) + _, err = io.ReadFull(reader, p) + if err != nil { + return nil, err + } + return p, nil +} + +func ReadUint(reader io.Reader) (uint64, error) { + var x uint64 + var s uint + i := 0 + for { + b, err := ReadByte(reader) + if err != nil { + return x, err + } + if b < 0x80 { + if i > 9 || i == 9 && b > 1 { + return x, errors.New("overflow") + } + return x | uint64(b)<> 1) + if err != nil { + return x, err + } + if ux&1 != 0 { + x = ^x + } + return x, err +} + +func ReadBoolean(reader io.Reader) (bool, error) { + p := make([]byte, 1) + _, err := io.ReadFull(reader, p) + if err != nil { + return false, err + } + return p[0] == 1, nil +} + +func ReadString(reader io.Reader) (string, error) { + l, err := ReadUint(reader) + if err != nil { + return "", err + } + if l > 10e6 { + return "", errors.New("Too long string") + } + buf := make([]byte, l) + _, err = io.ReadFull(reader, buf) + if err != nil { + return "", err + } + return string(buf), nil +} + +func ReadJson(reader io.Reader) (interface{}, error) { + jsonData, err := ReadData(reader) + if err != nil { + return nil, err + } + var v interface{} + if err = json.Unmarshal(jsonData, &v); err != nil { + return nil, err + } + return v, nil +} + +func WriteUint(v uint64, buf []byte, p int) int { + for v >= 0x80 { + buf[p] = byte(v) | 0x80 + v >>= 7 + p++ + } + buf[p] = byte(v) + return p + 1 +} + +func WriteInt(v int64, buf []byte, p int) int { + uv := uint64(v) << 1 + if v < 0 { + uv = ^uv + } + return WriteUint(uv, buf, p) +} + +func WriteBoolean(v bool, buf []byte, p int) int { + if v { + buf[p] = 1 + } else { + buf[p] = 0 + } + return p + 1 +} + +func WriteString(str string, buf []byte, p int) int { + p = WriteUint(uint64(len(str)), buf, p) + return p + copy(buf[p:], str) +} + +func WriteData(data []byte, buf []byte, p int) int { + p = WriteUint(uint64(len(data)), buf, p) + return p + copy(buf[p:], data) +} + +func WriteJson(v interface{}, buf []byte, p int) int { + data, err := json.Marshal(v) + if err != nil { + log.Printf("JSON encoding error: %v", err) + return WriteString("null", buf, p) + } + return WriteData(data, buf, p) +} \ No newline at end of file diff --git a/backend/pkg/messages/read_message.go b/backend/pkg/messages/read_message.go new file mode 100644 index 000000000..2efa8198a --- /dev/null +++ b/backend/pkg/messages/read_message.go @@ -0,0 +1,678 @@ +// Auto-generated, do not edit +package messages + +import ( + "fmt" + "io" +) + +func ReadMessage(reader io.Reader) (Message, error) { + t, err := ReadUint(reader); + if err != nil { + return nil, err + } + switch t { + + case 80: + msg := &BatchMeta{ meta: &meta{ TypeID: 80} } + if msg.PageNo, err = ReadUint(reader); err != nil { return nil, err } +if msg.FirstIndex, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadInt(reader); err != nil { return nil, err } + return msg, nil + + case 0: + msg := &Timestamp{ meta: &meta{ TypeID: 0} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 1: + msg := &SessionStart{ meta: &meta{ TypeID: 1} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.ProjectID, err = ReadUint(reader); err != nil { return nil, err } +if msg.TrackerVersion, err = ReadString(reader); err != nil { return nil, err } +if msg.RevID, err = ReadString(reader); err != nil { return nil, err } +if msg.UserUUID, err = ReadString(reader); err != nil { return nil, err } +if msg.UserAgent, err = ReadString(reader); err != nil { return nil, err } +if msg.UserOS, err = ReadString(reader); err != nil { return nil, err } +if msg.UserOSVersion, err = ReadString(reader); err != nil { return nil, err } +if msg.UserBrowser, err = ReadString(reader); err != nil { return nil, err } +if msg.UserBrowserVersion, err = ReadString(reader); err != nil { return nil, err } +if msg.UserDevice, err = ReadString(reader); err != nil { return nil, err } +if msg.UserDeviceType, err = ReadString(reader); err != nil { return nil, err } +if msg.UserDeviceMemorySize, err = ReadUint(reader); err != nil { return nil, err } +if msg.UserDeviceHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.UserCountry, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 3: + msg := &SessionEnd{ meta: &meta{ TypeID: 3} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 4: + msg := &SetPageLocation{ meta: &meta{ TypeID: 4} } + if msg.URL, err = ReadString(reader); err != nil { return nil, err } +if msg.Referrer, err = ReadString(reader); err != nil { return nil, err } +if msg.NavigationStart, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 5: + msg := &SetViewportSize{ meta: &meta{ TypeID: 5} } + if msg.Width, err = ReadUint(reader); err != nil { return nil, err } +if msg.Height, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 6: + msg := &SetViewportScroll{ meta: &meta{ TypeID: 6} } + if msg.X, err = ReadInt(reader); err != nil { return nil, err } +if msg.Y, err = ReadInt(reader); err != nil { return nil, err } + return msg, nil + + case 7: + msg := &CreateDocument{ meta: &meta{ TypeID: 7} } + + return msg, nil + + case 8: + msg := &CreateElementNode{ meta: &meta{ TypeID: 8} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.ParentID, err = ReadUint(reader); err != nil { return nil, err } +if msg.index, err = ReadUint(reader); err != nil { return nil, err } +if msg.Tag, err = ReadString(reader); err != nil { return nil, err } +if msg.SVG, err = ReadBoolean(reader); err != nil { return nil, err } + return msg, nil + + case 9: + msg := &CreateTextNode{ meta: &meta{ TypeID: 9} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.ParentID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Index, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 10: + msg := &MoveNode{ meta: &meta{ TypeID: 10} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.ParentID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Index, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 11: + msg := &RemoveNode{ meta: &meta{ TypeID: 11} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 12: + msg := &SetNodeAttribute{ meta: &meta{ TypeID: 12} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 13: + msg := &RemoveNodeAttribute{ meta: &meta{ TypeID: 13} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 14: + msg := &SetNodeData{ meta: &meta{ TypeID: 14} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Data, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 15: + msg := &SetCSSData{ meta: &meta{ TypeID: 15} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Data, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 16: + msg := &SetNodeScroll{ meta: &meta{ TypeID: 16} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.X, err = ReadInt(reader); err != nil { return nil, err } +if msg.Y, err = ReadInt(reader); err != nil { return nil, err } + return msg, nil + + case 17: + msg := &SetInputTarget{ meta: &meta{ TypeID: 17} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Label, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 18: + msg := &SetInputValue{ meta: &meta{ TypeID: 18} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } +if msg.Mask, err = ReadInt(reader); err != nil { return nil, err } + return msg, nil + + case 19: + msg := &SetInputChecked{ meta: &meta{ TypeID: 19} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Checked, err = ReadBoolean(reader); err != nil { return nil, err } + return msg, nil + + case 20: + msg := &MouseMove{ meta: &meta{ TypeID: 20} } + if msg.X, err = ReadUint(reader); err != nil { return nil, err } +if msg.Y, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 21: + msg := &MouseClick{ meta: &meta{ TypeID: 21} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err } +if msg.Label, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 22: + msg := &ConsoleLog{ meta: &meta{ TypeID: 22} } + if msg.Level, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 23: + msg := &PageLoadTiming{ meta: &meta{ TypeID: 23} } + if msg.RequestStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.ResponseStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.ResponseEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.DomContentLoadedEventStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.DomContentLoadedEventEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.LoadEventStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.LoadEventEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.FirstPaint, err = ReadUint(reader); err != nil { return nil, err } +if msg.FirstContentfulPaint, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 24: + msg := &PageRenderTiming{ meta: &meta{ TypeID: 24} } + if msg.SpeedIndex, err = ReadUint(reader); err != nil { return nil, err } +if msg.VisuallyComplete, err = ReadUint(reader); err != nil { return nil, err } +if msg.TimeToInteractive, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 25: + msg := &JSException{ meta: &meta{ TypeID: 25} } + if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Message, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 26: + msg := &RawErrorEvent{ meta: &meta{ TypeID: 26} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Source, err = ReadString(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Message, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 27: + msg := &RawCustomEvent{ meta: &meta{ TypeID: 27} } + if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 28: + msg := &UserID{ meta: &meta{ TypeID: 28} } + if msg.ID, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 29: + msg := &UserAnonymousID{ meta: &meta{ TypeID: 29} } + if msg.ID, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 30: + msg := &Metadata{ meta: &meta{ TypeID: 30} } + if msg.Key, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 31: + msg := &PageEvent{ meta: &meta{ TypeID: 31} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.URL, err = ReadString(reader); err != nil { return nil, err } +if msg.Referrer, err = ReadString(reader); err != nil { return nil, err } +if msg.Loaded, err = ReadBoolean(reader); err != nil { return nil, err } +if msg.RequestStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.ResponseStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.ResponseEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.DomContentLoadedEventStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.DomContentLoadedEventEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.LoadEventStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.LoadEventEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.FirstPaint, err = ReadUint(reader); err != nil { return nil, err } +if msg.FirstContentfulPaint, err = ReadUint(reader); err != nil { return nil, err } +if msg.SpeedIndex, err = ReadUint(reader); err != nil { return nil, err } +if msg.VisuallyComplete, err = ReadUint(reader); err != nil { return nil, err } +if msg.TimeToInteractive, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 32: + msg := &InputEvent{ meta: &meta{ TypeID: 32} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } +if msg.ValueMasked, err = ReadBoolean(reader); err != nil { return nil, err } +if msg.Label, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 33: + msg := &ClickEvent{ meta: &meta{ TypeID: 33} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err } +if msg.Label, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 34: + msg := &ErrorEvent{ meta: &meta{ TypeID: 34} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Source, err = ReadString(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Message, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 35: + msg := &ResourceEvent{ meta: &meta{ TypeID: 35} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } +if msg.TTFB, err = ReadUint(reader); err != nil { return nil, err } +if msg.HeaderSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.EncodedBodySize, err = ReadUint(reader); err != nil { return nil, err } +if msg.DecodedBodySize, err = ReadUint(reader); err != nil { return nil, err } +if msg.URL, err = ReadString(reader); err != nil { return nil, err } +if msg.Type, err = ReadString(reader); err != nil { return nil, err } +if msg.Success, err = ReadBoolean(reader); err != nil { return nil, err } +if msg.Method, err = ReadString(reader); err != nil { return nil, err } +if msg.Status, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 36: + msg := &CustomEvent{ meta: &meta{ TypeID: 36} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 37: + msg := &CSSInsertRule{ meta: &meta{ TypeID: 37} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Rule, err = ReadString(reader); err != nil { return nil, err } +if msg.Index, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 38: + msg := &CSSDeleteRule{ meta: &meta{ TypeID: 38} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Index, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 39: + msg := &Fetch{ meta: &meta{ TypeID: 39} } + if msg.Method, err = ReadString(reader); err != nil { return nil, err } +if msg.URL, err = ReadString(reader); err != nil { return nil, err } +if msg.Request, err = ReadString(reader); err != nil { return nil, err } +if msg.Response, err = ReadString(reader); err != nil { return nil, err } +if msg.Status, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 40: + msg := &Profiler{ meta: &meta{ TypeID: 40} } + if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } +if msg.Args, err = ReadString(reader); err != nil { return nil, err } +if msg.Result, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 41: + msg := &OTable{ meta: &meta{ TypeID: 41} } + if msg.Key, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 42: + msg := &StateAction{ meta: &meta{ TypeID: 42} } + if msg.Type, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 43: + msg := &StateActionEvent{ meta: &meta{ TypeID: 43} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Type, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 44: + msg := &Redux{ meta: &meta{ TypeID: 44} } + if msg.Action, err = ReadString(reader); err != nil { return nil, err } +if msg.State, err = ReadString(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 45: + msg := &Vuex{ meta: &meta{ TypeID: 45} } + if msg.Mutation, err = ReadString(reader); err != nil { return nil, err } +if msg.State, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 46: + msg := &MobX{ meta: &meta{ TypeID: 46} } + if msg.Type, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 47: + msg := &NgRx{ meta: &meta{ TypeID: 47} } + if msg.Action, err = ReadString(reader); err != nil { return nil, err } +if msg.State, err = ReadString(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 48: + msg := &GraphQL{ meta: &meta{ TypeID: 48} } + if msg.OperationKind, err = ReadString(reader); err != nil { return nil, err } +if msg.OperationName, err = ReadString(reader); err != nil { return nil, err } +if msg.Variables, err = ReadString(reader); err != nil { return nil, err } +if msg.Response, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 49: + msg := &PerformanceTrack{ meta: &meta{ TypeID: 49} } + if msg.Frames, err = ReadInt(reader); err != nil { return nil, err } +if msg.Ticks, err = ReadInt(reader); err != nil { return nil, err } +if msg.TotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.UsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 50: + msg := &GraphQLEvent{ meta: &meta{ TypeID: 50} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 52: + msg := &DOMDrop{ meta: &meta{ TypeID: 52} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 53: + msg := &ResourceTiming{ meta: &meta{ TypeID: 53} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } +if msg.TTFB, err = ReadUint(reader); err != nil { return nil, err } +if msg.HeaderSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.EncodedBodySize, err = ReadUint(reader); err != nil { return nil, err } +if msg.DecodedBodySize, err = ReadUint(reader); err != nil { return nil, err } +if msg.URL, err = ReadString(reader); err != nil { return nil, err } +if msg.Initiator, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 54: + msg := &ConnectionInformation{ meta: &meta{ TypeID: 54} } + if msg.Downlink, err = ReadUint(reader); err != nil { return nil, err } +if msg.Type, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 55: + msg := &SetPageVisibility{ meta: &meta{ TypeID: 55} } + if msg.hidden, err = ReadBoolean(reader); err != nil { return nil, err } + return msg, nil + + case 56: + msg := &PerformanceTrackAggr{ meta: &meta{ TypeID: 56} } + if msg.TimestampStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.TimestampEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinFPS, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgFPS, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxFPS, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinCPU, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgCPU, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxCPU, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinTotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgTotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxTotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinUsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgUsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxUsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 59: + msg := &LongTask{ meta: &meta{ TypeID: 59} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } +if msg.Context, err = ReadUint(reader); err != nil { return nil, err } +if msg.ContainerType, err = ReadUint(reader); err != nil { return nil, err } +if msg.ContainerSrc, err = ReadString(reader); err != nil { return nil, err } +if msg.ContainerId, err = ReadString(reader); err != nil { return nil, err } +if msg.ContainerName, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 60: + msg := &SetNodeAttributeURLBased{ meta: &meta{ TypeID: 60} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } +if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 61: + msg := &SetCSSDataURLBased{ meta: &meta{ TypeID: 61} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Data, err = ReadString(reader); err != nil { return nil, err } +if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 62: + msg := &IssueEvent{ meta: &meta{ TypeID: 62} } + if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Type, err = ReadString(reader); err != nil { return nil, err } +if msg.ContextString, err = ReadString(reader); err != nil { return nil, err } +if msg.Context, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 63: + msg := &TechnicalInfo{ meta: &meta{ TypeID: 63} } + if msg.Type, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 64: + msg := &CustomIssue{ meta: &meta{ TypeID: 64} } + if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 65: + msg := &PageClose{ meta: &meta{ TypeID: 65} } + + return msg, nil + + case 66: + msg := &AssetCache{ meta: &meta{ TypeID: 66} } + if msg.URL, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 67: + msg := &CSSInsertRuleURLBased{ meta: &meta{ TypeID: 67} } + if msg.ID, err = ReadUint(reader); err != nil { return nil, err } +if msg.Rule, err = ReadString(reader); err != nil { return nil, err } +if msg.Index, err = ReadUint(reader); err != nil { return nil, err } +if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 90: + msg := &IOSSessionStart{ meta: &meta{ TypeID: 90} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.ProjectID, err = ReadUint(reader); err != nil { return nil, err } +if msg.TrackerVersion, err = ReadString(reader); err != nil { return nil, err } +if msg.RevID, err = ReadString(reader); err != nil { return nil, err } +if msg.UserUUID, err = ReadString(reader); err != nil { return nil, err } +if msg.UserOS, err = ReadString(reader); err != nil { return nil, err } +if msg.UserOSVersion, err = ReadString(reader); err != nil { return nil, err } +if msg.UserDevice, err = ReadString(reader); err != nil { return nil, err } +if msg.UserDeviceType, err = ReadString(reader); err != nil { return nil, err } +if msg.UserCountry, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 91: + msg := &IOSSessionEnd{ meta: &meta{ TypeID: 91} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 92: + msg := &IOSMetadata{ meta: &meta{ TypeID: 92} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Key, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 93: + msg := &IOSCustomEvent{ meta: &meta{ TypeID: 93} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 94: + msg := &IOSUserID{ meta: &meta{ TypeID: 94} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 95: + msg := &IOSUserAnonymousID{ meta: &meta{ TypeID: 95} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 96: + msg := &IOSScreenChanges{ meta: &meta{ TypeID: 96} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.SkipData, err = ReadData(reader); err != nil { return nil, err } + return msg, nil + + case 97: + msg := &IOSCrash{ meta: &meta{ TypeID: 97} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Reason, err = ReadString(reader); err != nil { return nil, err } +if msg.Stacktrace, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 98: + msg := &IOSScreenEnter{ meta: &meta{ TypeID: 98} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Title, err = ReadString(reader); err != nil { return nil, err } +if msg.ViewName, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 99: + msg := &IOSScreenLeave{ meta: &meta{ TypeID: 99} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Title, err = ReadString(reader); err != nil { return nil, err } +if msg.ViewName, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 100: + msg := &IOSClickEvent{ meta: &meta{ TypeID: 100} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Label, err = ReadString(reader); err != nil { return nil, err } +if msg.X, err = ReadUint(reader); err != nil { return nil, err } +if msg.Y, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 101: + msg := &IOSInputEvent{ meta: &meta{ TypeID: 101} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Value, err = ReadString(reader); err != nil { return nil, err } +if msg.ValueMasked, err = ReadBoolean(reader); err != nil { return nil, err } +if msg.Label, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 102: + msg := &IOSPerformanceEvent{ meta: &meta{ TypeID: 102} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Name, err = ReadString(reader); err != nil { return nil, err } +if msg.Value, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 103: + msg := &IOSLog{ meta: &meta{ TypeID: 103} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Severity, err = ReadString(reader); err != nil { return nil, err } +if msg.Content, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 104: + msg := &IOSInternalError{ meta: &meta{ TypeID: 104} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Content, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + case 105: + msg := &IOSNetworkCall{ meta: &meta{ TypeID: 105} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Length, err = ReadUint(reader); err != nil { return nil, err } +if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } +if msg.Headers, err = ReadString(reader); err != nil { return nil, err } +if msg.Body, err = ReadString(reader); err != nil { return nil, err } +if msg.URL, err = ReadString(reader); err != nil { return nil, err } +if msg.Success, err = ReadBoolean(reader); err != nil { return nil, err } +if msg.Method, err = ReadString(reader); err != nil { return nil, err } +if msg.Status, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 110: + msg := &IOSPerformanceAggregated{ meta: &meta{ TypeID: 110} } + if msg.TimestampStart, err = ReadUint(reader); err != nil { return nil, err } +if msg.TimestampEnd, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinFPS, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgFPS, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxFPS, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinCPU, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgCPU, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxCPU, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinMemory, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgMemory, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxMemory, err = ReadUint(reader); err != nil { return nil, err } +if msg.MinBattery, err = ReadUint(reader); err != nil { return nil, err } +if msg.AvgBattery, err = ReadUint(reader); err != nil { return nil, err } +if msg.MaxBattery, err = ReadUint(reader); err != nil { return nil, err } + return msg, nil + + case 111: + msg := &IOSIssueEvent{ meta: &meta{ TypeID: 111} } + if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } +if msg.Type, err = ReadString(reader); err != nil { return nil, err } +if msg.ContextString, err = ReadString(reader); err != nil { return nil, err } +if msg.Context, err = ReadString(reader); err != nil { return nil, err } +if msg.Payload, err = ReadString(reader); err != nil { return nil, err } + return msg, nil + + } + return nil, fmt.Errorf("Unknown message code: %v", t) +} diff --git a/backend/pkg/queue/import.go b/backend/pkg/queue/import.go new file mode 100644 index 000000000..2bca9c8fd --- /dev/null +++ b/backend/pkg/queue/import.go @@ -0,0 +1,15 @@ +package queue + +import ( + "openreplay/backend/pkg/redisstream" + "openreplay/backend/pkg/queue/types" +) + +func NewConsumer(group string, topics []string, handler types.MessageHandler) types.Consumer { + return redisstream.NewConsumer(group, topics, handler) +} + +func NewProducer() types.Producer { + return redisstream.NewProducer() +} + diff --git a/backend/pkg/queue/messages.go b/backend/pkg/queue/messages.go new file mode 100644 index 000000000..eca4a4d49 --- /dev/null +++ b/backend/pkg/queue/messages.go @@ -0,0 +1,19 @@ +package queue + +import ( + "log" + + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/queue/types" +) + + +func NewMessageConsumer(group string, topics []string, handler types.DecodedMessageHandler) types.Consumer { + return NewConsumer(group, topics, func(sessionID uint64, value []byte, meta *types.Meta) { + if err := messages.ReadBatch(value, func(msg messages.Message) { + handler(sessionID, msg, meta) + }); err != nil { + log.Printf("Decode error: %v\n", err) + } + }) +} diff --git a/backend/pkg/queue/types/types.go b/backend/pkg/queue/types/types.go new file mode 100644 index 000000000..b671323d0 --- /dev/null +++ b/backend/pkg/queue/types/types.go @@ -0,0 +1,31 @@ +package types + +import ( + "openreplay/backend/pkg/messages" +) + +type Consumer interface { + ConsumeNext() error + DisableAutoCommit() + Commit() error + CommitBack(gap int64) error + Close() +} + + +type Producer interface { + Produce(topic string, key uint64, value []byte) error + Close(timeout int) + Flush(timeout int) +} + + +type Meta struct { + ID uint64 + Topic string + Timestamp int64 +} + +type MessageHandler func(uint64, []byte, *Meta) +type DecodedMessageHandler func(uint64, messages.Message, *Meta) + diff --git a/backend/pkg/redisstream/consumer.go b/backend/pkg/redisstream/consumer.go new file mode 100644 index 000000000..164ee9236 --- /dev/null +++ b/backend/pkg/redisstream/consumer.go @@ -0,0 +1,170 @@ +package redisstream + +import ( + "net" + "strconv" + "strings" + "log" + "sort" + "time" + + "github.com/pkg/errors" + _redis "github.com/go-redis/redis" + + "openreplay/backend/pkg/queue/types" +) + + + +type idsInfo struct{ + id []string + ts []int64 +} +type streamPendingIDsMap map[string]*idsInfo + +type Consumer struct { + redis *_redis.Client + streams []string + group string + messageHandler types.MessageHandler + idsPending streamPendingIDsMap + lastTs int64 + autoCommit bool +} + +func NewConsumer(group string, streams []string, messageHandler types.MessageHandler) *Consumer { + redis := getRedisClient() + for _, stream := range streams { + err := redis.XGroupCreateMkStream(stream, group, "0").Err() + if err != nil && err.Error() != "BUSYGROUP Consumer Group name already exists" { + log.Fatalln(err) + } + } + + + idsPending := make(streamPendingIDsMap) + + streamsCount := len(streams) + for i := 0; i < streamsCount; i++ { + // ">" is for never-delivered messages. + // Otherwise - never acknoledged only + // TODO: understand why in case of "0" it eats 100% cpu + streams = append(streams, ">") + + idsPending[streams[i]] = new(idsInfo) + } + + return &Consumer{ + redis: redis, + messageHandler: messageHandler, + streams: streams, + group: group, + autoCommit: true, + idsPending: idsPending, + } +} + +const READ_COUNT = 10 + +func (c *Consumer) ConsumeNext() error { + // MBTODO: read in go routine, send messages to channel + res, err := c.redis.XReadGroup(&_redis.XReadGroupArgs{ + Group: c.group, + Consumer: c.group, + Streams: c.streams, + Count: int64(READ_COUNT), + Block: 200 * time.Millisecond, + }).Result() + if err != nil { + if err, ok := err.(net.Error); ok && err.Timeout() { + return nil + } + if err == _redis.Nil { + return nil + } + return err + } + for _, r := range res { + for _, m := range r.Messages { + sessionIDString, ok := m.Values["sessionID"].(string) + if !ok { + return errors.Errorf("Can not cast value for messageID %v", m.ID) + } + sessionID, err := strconv.ParseUint(sessionIDString, 10, 64) + if err != nil { + return errors.Wrapf(err, "Can not parse sessionID '%v' for messageID %v", sessionID, m.ID) + } + valueString, ok := m.Values["value"].(string) + if !ok { + return errors.Errorf("Can not cast value for messageID %v", m.ID) + } + // assumming that ID has a correct format + idParts := strings.Split(m.ID, "-") + ts, _ := strconv.ParseUint(idParts[0], 10, 64) + idx, _ := strconv.ParseUint(idParts[1], 10, 64) + if idx > 0x1FFF { + return errors.New("Too many messages per ms in redis") + } + c.messageHandler(sessionID, []byte(valueString), &types.Meta{ + Topic: r.Stream, + Timestamp: int64(ts), + ID: ts << 13 | (idx & 0x1FFF), // Max: 4096 messages/ms for 69 years + }) + if c.autoCommit { + if err = c.redis.XAck(r.Stream, c.group, m.ID).Err(); err != nil { + return errors.Wrapf(err, "Acknoledgment error for messageID %v", m.ID) + } + } else { + c.lastTs = int64(ts) + c.idsPending[r.Stream].id = append(c.idsPending[r.Stream].id, m.ID) + c.idsPending[r.Stream].ts = append(c.idsPending[r.Stream].ts, int64(ts)) + } + + } + } + return nil +} + +func (c *Consumer) Commit() error { + for stream, idsInfo := range c.idsPending { + if len(idsInfo.id) == 0 { + continue + } + if err := c.redis.XAck(stream, c.group, idsInfo.id...).Err(); err != nil { + return errors.Wrapf(err, "Redisstreams: Acknoledgment error on commit %v", err) + } + c.idsPending[stream].id = nil + c.idsPending[stream].ts = nil + } + return nil +} + +func (c *Consumer) CommitBack(gap int64) error { + if c.lastTs == 0 { + return nil + } + maxTs := c.lastTs - gap + + for stream, idsInfo := range c.idsPending { + if len(idsInfo.id) == 0 { + continue + } + maxI := sort.Search(len(idsInfo.ts), func(i int) bool { + return idsInfo.ts[i] > maxTs + }) + if err := c.redis.XAck(stream, c.group, idsInfo.id[:maxI]...).Err(); err != nil { + return errors.Wrapf(err, "Redisstreams: Acknoledgment error on commit %v", err) + } + c.idsPending[stream].id = idsInfo.id[maxI:] + c.idsPending[stream].ts = idsInfo.ts[maxI:] + } + return nil +} + +func (c *Consumer) DisableAutoCommit() { + //c.autoCommit = false +} + +func (c *Consumer) Close() { + // noop +} \ No newline at end of file diff --git a/backend/pkg/redisstream/producer.go b/backend/pkg/redisstream/producer.go new file mode 100644 index 000000000..e67200a4f --- /dev/null +++ b/backend/pkg/redisstream/producer.go @@ -0,0 +1,44 @@ +package redisstream + +import ( + "github.com/go-redis/redis" + + "openreplay/backend/pkg/env" +) + + +type Producer struct { + redis *redis.Client + maxLenApprox int64 +} + +func NewProducer() *Producer { + return &Producer{ + redis: getRedisClient(), + maxLenApprox: int64(env.Uint64("REDIS_STREAMS_MAX_LEN")), + } +} + +func (p *Producer) Produce(topic string, key uint64, value []byte) error { + args := &redis.XAddArgs{ + Stream: topic, + Values: map[string]interface{}{ + "sessionID": key, + "value": value, + }, + } + args.MaxLenApprox = p.maxLenApprox + + _, err := p.redis.XAdd(args).Result() + if err != nil { + return err + } + return nil +} + +func (p *Producer) Close(_ int) { + // noop +} +func (p *Producer) Flush(_ int) { + // noop +} diff --git a/backend/pkg/redisstream/redis.go b/backend/pkg/redisstream/redis.go new file mode 100644 index 000000000..dea4afe9b --- /dev/null +++ b/backend/pkg/redisstream/redis.go @@ -0,0 +1,26 @@ +package redisstream + +import ( + "log" + + "github.com/go-redis/redis" + + "openreplay/backend/pkg/env" +) + + +var redisClient *redis.Client + + +func getRedisClient() *redis.Client { + if redisClient != nil { + return redisClient + } + redisClient = redis.NewClient(&redis.Options{ + Addr: env.String("REDIS_STRING"), + }) + if _, err := redisClient.Ping().Result(); err != nil { + log.Fatalln(err) + } + return redisClient +} \ No newline at end of file diff --git a/backend/pkg/storage/s3.go b/backend/pkg/storage/s3.go new file mode 100644 index 000000000..0f55e3851 --- /dev/null +++ b/backend/pkg/storage/s3.go @@ -0,0 +1,98 @@ +package storage + +import ( + "io" + "strconv" + "sort" + + _s3 "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go/service/s3/s3manager" + + "openreplay/backend/pkg/env" +) + +type S3 struct { + uploader *s3manager.Uploader + svc *_s3.S3 + bucket *string +} + + +func NewS3(region string, bucket string) *S3 { + sess := env.AWSSessionOnRegion(region) + return &S3{ + uploader: s3manager.NewUploader(sess), + svc: _s3.New(sess), // AWS Docs: "These clients are safe to use concurrently." + bucket: &bucket, + } +} + +func (s3 *S3) Upload(reader io.Reader, key string, contentType string, gzipped bool) error { + cacheControl := "max-age=2628000, immutable, private" + var contentEncoding *string + if gzipped { + gzipStr := "gzip" + contentEncoding = &gzipStr + } + _, err := s3.uploader.Upload(&s3manager.UploadInput{ + Body: reader, + Bucket: s3.bucket, + Key: &key, + ContentType: &contentType, + CacheControl: &cacheControl, + ContentEncoding: contentEncoding, + }) + return err +} + +func (s3 *S3) Get(key string) (io.ReadCloser, error) { + out, err := s3.svc.GetObject(&_s3.GetObjectInput{ + Bucket: s3.bucket, + Key: &key, + }) + if err != nil { + return nil, err + } + return out.Body, nil +} + +func (s3 *S3) Exists(key string) bool { + _, err := s3.svc.HeadObject(&_s3.HeadObjectInput{ + Bucket: s3.bucket, + Key: &key, + }) + if err == nil { + return true + } + return false +} + + +const MAX_RETURNING_COUNT = 40 +func (s3 *S3) GetFrequentlyUsedKeys(projectID uint64) ([]string, error) { + prefix := strconv.FormatUint(projectID, 10) + "/" + output, err := s3.svc.ListObjectsV2(&_s3.ListObjectsV2Input{ + Bucket: s3.bucket, + Prefix: &prefix, + }) + if err != nil { + return nil, err + } + //pagination may be here + + list := output.Contents + max := len(list) + if (max > MAX_RETURNING_COUNT) { + max = MAX_RETURNING_COUNT + sort.Slice(list, func(i, j int) bool { + return list[i].LastModified.After(*(list[j].LastModified)) + }) + } + + var keyList []string + s := len(prefix) + for _, obj := range list[:max] { + keyList = append(keyList, (*obj.Key)[s:]) + } + return keyList, nil +} \ No newline at end of file diff --git a/backend/pkg/token/http.go b/backend/pkg/token/http.go new file mode 100644 index 000000000..898bad559 --- /dev/null +++ b/backend/pkg/token/http.go @@ -0,0 +1,18 @@ +package token + +import ( + "errors" + "net/http" + "strings" +) + +const BEARER_SCHEMA = "Bearer " + +func (tokenizer *Tokenizer) ParseFromHTTPRequest(r *http.Request) (*TokenData, error) { + header := r.Header.Get("Authorization") + if !strings.HasPrefix(header, BEARER_SCHEMA) { + return nil, errors.New("Missing token") + } + token := header[len(BEARER_SCHEMA):] + return tokenizer.Parse(token) +} diff --git a/backend/pkg/token/tokenizer.go b/backend/pkg/token/tokenizer.go new file mode 100644 index 000000000..3f1069a63 --- /dev/null +++ b/backend/pkg/token/tokenizer.go @@ -0,0 +1,65 @@ +package token + +import ( + "crypto/hmac" + "crypto/sha256" + "errors" + "strconv" + "strings" + "time" + + "github.com/btcsuite/btcutil/base58" +) + +var EXPIRED = errors.New("token expired") + +type Tokenizer struct { + secret []byte +} + +func NewTokenizer(secret string) *Tokenizer { + return &Tokenizer{[]byte(secret)} +} + +type TokenData struct { + ID uint64 + ExpTime int64 +} + +func (tokenizer *Tokenizer) sign(body string) []byte { + mac := hmac.New(sha256.New, tokenizer.secret) + mac.Write([]byte(body)) + return mac.Sum(nil) +} + +func (tokenizer *Tokenizer) Compose(d TokenData) string { + body := strconv.FormatUint(d.ID, 36) + + "." + strconv.FormatInt(d.ExpTime, 36) + sign := base58.Encode(tokenizer.sign(body)) + return body + "." + sign +} + +func (tokenizer *Tokenizer) Parse(token string) (*TokenData, error) { + data := strings.Split(token, ".") + if len(data) != 3 { + return nil, errors.New("wrong token format") + } + if !hmac.Equal( + base58.Decode(data[len(data)-1]), + tokenizer.sign(data[0]+"."+data[1]), + ) { + return nil, errors.New("wrong token sign") + } + id, err := strconv.ParseUint(data[0], 36, 64) + if err != nil { + return nil, err + } + expTime, err := strconv.ParseInt(data[1], 36, 64) + if err != nil { + return nil, err + } + if expTime <= time.Now().UnixNano()/1e6 { + return &TokenData{id,expTime}, EXPIRED + } + return &TokenData{id,expTime}, nil +} diff --git a/backend/pkg/url/assets/css.go b/backend/pkg/url/assets/css.go new file mode 100644 index 000000000..728239837 --- /dev/null +++ b/backend/pkg/url/assets/css.go @@ -0,0 +1,63 @@ +package assets + +import ( + "regexp" + "sort" + "strings" +) + +// TODO: ignore data: , escaped quotes , spaces between brackets? +var cssURLs = regexp.MustCompile(`url\(("[^"]*"|'[^']*'|[^)]*)\)`) +var cssImports = regexp.MustCompile(`@import "(.*?)"`) + +func cssUrlsIndex(css string) [][]int { + var idxs [][]int + for _, match := range cssURLs.FindAllStringSubmatchIndex(css, -1) { + idxs = append(idxs, match[2:]) + } + for _, match := range cssImports.FindAllStringSubmatchIndex(css, -1) { + idxs = append(idxs, match[2:]) + } + sort.Slice(idxs, func(i, j int) bool { + return idxs[i][0] > idxs[j][0] + }) + return idxs +} + +func unquote(str string) (string, string) { + str = strings.TrimSpace(str) + if len(str) <= 2 { + return str, "" + } + if str[0] == '"' && str[len(str)-1] == '"' { + return str[1 : len(str)-1], "\"" + } + if str[0] == '\'' && str[len(str)-1] == '\'' { + return str[1 : len(str)-1], "'" + } + return str, "" +} + +func ExtractURLsFromCSS(css string) []string { + indexes := cssUrlsIndex(css) + urls := make([]string, len(indexes)) + for _, idx := range indexes { + + f := idx[0] + t := idx[1] + rawurl, _ := unquote(css[f:t]) + urls = append(urls, rawurl) + } + return urls +} + +func (r *Rewriter) RewriteCSS(sessionID uint64, baseurl string, css string) string { + for _, idx := range cssUrlsIndex(css) { + f := idx[0] + t := idx[1] + rawurl, q := unquote(css[f:t]) + // why exactly quote back? + css = css[:f] + q + r.RewriteURL(sessionID, baseurl, rawurl) + q + css[t:] + } + return strings.Replace(css, ":hover", ".-asayer-hover", -1) +} diff --git a/backend/pkg/url/assets/rewriter.go b/backend/pkg/url/assets/rewriter.go new file mode 100644 index 000000000..025e3cd5d --- /dev/null +++ b/backend/pkg/url/assets/rewriter.go @@ -0,0 +1,21 @@ +package assets + +import ( + "log" + "net/url" +) + +type Rewriter struct { + assetsURL *url.URL +} + +func NewRewriter(baseOrigin string) *Rewriter { + assetsURL, err := url.Parse(baseOrigin) + if err != nil { + log.Fatal(err) + } + return &Rewriter{ + assetsURL: assetsURL, + } + +} diff --git a/backend/pkg/url/assets/url.go b/backend/pkg/url/assets/url.go new file mode 100644 index 000000000..9f6c2c267 --- /dev/null +++ b/backend/pkg/url/assets/url.go @@ -0,0 +1,98 @@ +package assets + +import ( + "net/url" + "path/filepath" + "strconv" +) + +func getSessionKey(sessionID uint64) string { + // Based on timestamp, changes once per week. Check out utils/flacker for understanding sessionID + return strconv.FormatUint(sessionID>>50, 10) +} + +func ResolveURL(baseurl string, rawurl string) string { + base, _ := url.ParseRequestURI(baseurl) // fn Only for base urls + u, _ := url.Parse(rawurl) // TODO: handle errors ? + if base == nil || u == nil { + return rawurl + } + return base.ResolveReference(u).String() // ResolveReference same as base.Parse(rawurl) +} + +func isRelativeCachable(relativeURL string) bool { + if len(relativeURL) == 0 || relativeURL[0] == '#' { + return false + } + return true +} +func isCachable(rawurl string) bool { + u, _ := url.Parse(rawurl) + if u == nil || u.User != nil { + return false + } + if u.Scheme != "http" && u.Scheme != "https" { + return false + } + ext := filepath.Ext(u.Path) + return ext == ".css" || + ext == ".woff" || + ext == ".woff2" || + ext == ".ttf" || + ext == ".otf" +} + +func GetFullCachableURL(baseURL string, relativeURL string) (string, bool) { + if !isRelativeCachable(relativeURL) { + return "", false + } + return ResolveURL(baseURL, relativeURL), true +} + + +const ASAYER_QUERY_START = "ASAYER_QUERY_ESCtRT" + +func getCachePath(rawurl string) string { + u, _ := url.Parse(rawurl) + s := "/" + u.Scheme + "/" + u.Hostname() + u.Path + if u.RawQuery != "" { + if (s[len(s) - 1] != '/') { + s += "/" + } + s += ASAYER_QUERY_START + url.PathEscape(u.RawQuery) + } + return s +} + +func getCachePathWithKey(sessionID uint64, rawurl string) string { + return getCachePath(rawurl) + "." + getSessionKey(sessionID) // Be carefull with slashes +} + +func GetCachePathForJS(rawurl string) string { + return getCachePath(rawurl) +} + +func GetCachePathForAssets(sessionID uint64, rawurl string) string { + return getCachePathWithKey(sessionID, rawurl) +} + + +func (r *Rewriter) RewriteURL(sessionID uint64, baseURL string, relativeURL string) string { + // TODO: put it in one check within GetFullCachableURL + if !isRelativeCachable(relativeURL) { + return relativeURL + } + fullURL := ResolveURL(baseURL, relativeURL) + if !isCachable(fullURL) { + return relativeURL + } + + u := url.URL{ + Path: r.assetsURL.Path + getCachePathWithKey(sessionID, fullURL), + Host: r.assetsURL.Host, + Scheme: r.assetsURL.Scheme, + } + + return u.String() +} + diff --git a/backend/pkg/url/method.go b/backend/pkg/url/method.go new file mode 100644 index 000000000..e7dd9eb49 --- /dev/null +++ b/backend/pkg/url/method.go @@ -0,0 +1,12 @@ +package url + +var METHODS = []string{ "GET", "HEAD", "POST" , "PUT" , "DELETE" , "CONNECT" , "OPTIONS" , "TRACE" , "PATCH" } + +func EnsureMethod(method string) string { + for _, m := range METHODS { + if m == method { + return method + } + } + return "" +} \ No newline at end of file diff --git a/backend/pkg/url/url.go b/backend/pkg/url/url.go new file mode 100644 index 000000000..b9181774d --- /dev/null +++ b/backend/pkg/url/url.go @@ -0,0 +1,18 @@ +package url + +import ( + "strings" + _url "net/url" +) + +func DiscardURLQuery(url string) string { + return strings.Split(url, "?")[0] +} + +func GetURLParts(rawURL string) (string, string, error) { + u, err := _url.Parse(rawURL) + if err != nil { + return "", "", err + } + return u.Host, u.RequestURI(), nil +} \ No newline at end of file diff --git a/backend/pkg/utime/utime.go b/backend/pkg/utime/utime.go new file mode 100644 index 000000000..e3b5a2751 --- /dev/null +++ b/backend/pkg/utime/utime.go @@ -0,0 +1,11 @@ +package utime + +import "time" + +func CurrentTimestamp() int64 { + return time.Now().UnixNano() / 1e6 +} + +func ToMilliseconds(t time.Time) int64 { + return t.UnixNano() / 1e6 +} diff --git a/backend/services/alerts/main.go b/backend/services/alerts/main.go new file mode 100644 index 000000000..c4398f470 --- /dev/null +++ b/backend/services/alerts/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "database/sql" + "log" + "os" + "os/signal" + "syscall" + "time" + + "github.com/ClickHouse/clickhouse-go" + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/db/postgres" +) + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + POSTGRES_STRING := env.String("POSTGRES_STRING") + CLICKHOUSE_STRING := env.String("CLICKHOUSE_STRING") + NOTIFICATIONS_STRING := env.String("ALERT_NOTIFICATION_STRING") + log.Printf("Notifications: %s \nCH: %s\n", NOTIFICATIONS_STRING, CLICKHOUSE_STRING) + pg := postgres.NewConn(POSTGRES_STRING) + defer pg.Close() + + ch, err := sql.Open("clickhouse", CLICKHOUSE_STRING) + if err != nil { + log.Fatal(err) + } + if err := ch.Ping(); err != nil { + if exception, ok := err.(*clickhouse.Exception); ok { + log.Printf("[%d] %s \n%s\n", exception.Code, exception.Message, exception.StackTrace) + } else { + log.Println(err) + } + return + } + + manager := NewManager(NOTIFICATIONS_STRING, ch, pg) + if err := pg.IterateAlerts(func(a *postgres.Alert, err error) { + if err != nil { + log.Printf("Postgres error: %v\n", err) + return + } + log.Printf("Alert initialization: %+v\n", *a) + //log.Printf("CreatedAt: %s\n", *a.CreatedAt) + err = manager.Update(a) + if err != nil { + log.Printf("Alert parse error: %v | Alert: %+v\n", err, *a) + return + } + }); err != nil { + log.Fatalf("Postgres error: %v\n", err) + } + + listener, err := postgres.NewAlertsListener(POSTGRES_STRING) + if err != nil { + log.Fatalf("Postgres listener error: %v\n", err) + } + defer listener.Close() + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + tickAlert := time.Tick(1 * time.Minute) + + log.Printf("Alert service started\n") + manager.RequestAll() + //return + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + listener.Close() + pg.Close() + os.Exit(0) + case <-tickAlert: + log.Printf("Requesting all...%d alerts\n", manager.Length()) + manager.RequestAll() + case iPointer := <-listener.Alerts: + log.Printf("Alert update: %+v\n", *iPointer) + //log.Printf("CreatedAt: %s\n", *iPointer.CreatedAt) + //log.Printf("Notification received for AlertId: %d\n", iPointer.AlertID) + err := manager.Update(iPointer) + if err != nil { + log.Printf("Alert parse error: %+v | Alert: %v\n", err, *iPointer) + } + case err := <-listener.Errors: + log.Printf("listener error: %v\n", err) + if err.Error() == "conn closed" { + panic("Listener conn lost") + } + } + } +} diff --git a/backend/services/alerts/manager.go b/backend/services/alerts/manager.go new file mode 100644 index 000000000..3f9e39851 --- /dev/null +++ b/backend/services/alerts/manager.go @@ -0,0 +1,169 @@ +package main + +import ( + "database/sql" + "fmt" + "log" + "sync" + "sync/atomic" + "time" + + "openreplay/backend/pkg/db/postgres" +) + +const CHParallelLimit = 2 + +var chCount int64 + +type manager struct { + notificationsUrl string + alertsCache map[uint32]*postgres.Alert + cacheMutex sync.Mutex + chParallel chan bool + ch *sql.DB + pg *postgres.Conn + pgMutex sync.Mutex + notifications map[uint32]*postgres.TenantNotification + notificationsGo *sync.WaitGroup + notificationsMutex sync.Mutex +} + +func NewManager(notificationsUrl string, ch *sql.DB, pg *postgres.Conn) *manager { + return &manager{ + notificationsUrl: notificationsUrl, + alertsCache: make(map[uint32]*postgres.Alert), + cacheMutex: sync.Mutex{}, + chParallel: make(chan bool, CHParallelLimit), + ch: ch, + pg: pg, + pgMutex: sync.Mutex{}, + notifications: make(map[uint32]*postgres.TenantNotification), + notificationsGo: &sync.WaitGroup{}, + notificationsMutex: sync.Mutex{}, + } + +} + +func (m *manager) Length() int { + return len(m.alertsCache) +} + +func (m *manager) Update(a *postgres.Alert) error { + m.cacheMutex.Lock() + defer m.cacheMutex.Unlock() + _, exists := m.alertsCache[a.AlertID] + if exists && a.DeletedAt != nil { + log.Println("deleting alert from memory") + delete(m.alertsCache, a.AlertID) + return nil + } else { + m.alertsCache[a.AlertID] = a + } + return nil +} +func (m *manager) processAlert(a *postgres.Alert) { + defer func() { + defer m.notificationsGo.Done() + <-m.chParallel + }() + if !a.CanCheck() { + //log.Printf("cannot check %+v", a) + //log.Printf("cannot check alertId %d", a.AlertID) + log.Printf("cannot check %s", a.Name) + return + } + //log.Printf("checking %+v", a) + log.Printf("quering %s", a.Name) + //--- For stats: + atomic.AddInt64(&chCount, 1) + q, err := a.Build() + if err != nil { + log.Println(err) + return + } + + //sub1, args, _ := q.ToSql() + //log.Println(sub1) + //log.Println(args) + //return + rows, err := q.RunWith(m.ch).Query() + + if err != nil { + log.Println(err) + return + } + defer rows.Close() + + for rows.Next() { + var ( + value sql.NullFloat64 + valid bool + ) + if err := rows.Scan(&value, &valid); err != nil { + log.Println(err) + continue + } + //log.Println(valid) + //log.Println(value.Valid) + if valid && value.Valid { + log.Printf("%s: valid", a.Name) + m.notificationsMutex.Lock() + m.notifications[a.AlertID] = &postgres.TenantNotification{ + TenantId: a.TenantId, + Title: a.Name, + Description: fmt.Sprintf("has been triggered, %s = %.0f (%s %.0f).", a.Query.Left, value.Float64, a.Query.Operator, a.Query.Right), + ButtonText: "Check metrics for more details", + ButtonUrl: fmt.Sprintf("/%d/metrics", a.ProjectID), + ImageUrl: nil, + Options: map[string]interface{}{"source": "ALERT", "sourceId": a.AlertID, "sourceMeta": a.DetectionMethod, "message": a.Options.Message, "projectId": a.ProjectID}, + } + m.notificationsMutex.Unlock() + } + } + +} +func (m *manager) RequestAll() { + now := time.Now().Unix() + m.cacheMutex.Lock() + for _, a := range m.alertsCache { + m.chParallel <- true + m.notificationsGo.Add(1) + go m.processAlert(a) + //m.processAlert(a) + } + //log.Println("releasing cache") + m.cacheMutex.Unlock() + //log.Println("waiting for all alerts to finish") + m.notificationsGo.Wait() + log.Printf("done %d CH queries in: %ds", chCount, time.Now().Unix()-now) + chCount = 0 + //log.Printf("Processing %d Notifications", len(m.notifications)) + m.notificationsMutex.Lock() + go m.ProcessNotifications(m.notifications) + m.notificationsMutex.Unlock() + m.notifications = make(map[uint32]*postgres.TenantNotification) + //log.Printf("Notifications purged: %d", len(m.notifications)) +} + +func (m *manager) ProcessNotifications(allNotifications map[uint32]*postgres.TenantNotification) { + //return + if len(allNotifications) == 0 { + log.Println("No notifications to process") + return + } + log.Printf("sending %d notifications", len(allNotifications)) + allIds := make([]uint32, 0, len(allNotifications)) + toSend := postgres.Notifications{ + Notifications: []*postgres.TenantNotification{}, + } + for k, n := range allNotifications { + //log.Printf("notification for %d", k) + allIds = append(allIds, k) + toSend.Notifications = append(toSend.Notifications, n) + } + toSend.Send(m.notificationsUrl) + if err := m.pg.SaveLastNotification(allIds); err != nil { + log.Printf("Error saving LastNotification time: %v", err) + return + } +} diff --git a/backend/services/assets/cacher/cacher.go b/backend/services/assets/cacher/cacher.go new file mode 100644 index 000000000..d9f39aa77 --- /dev/null +++ b/backend/services/assets/cacher/cacher.go @@ -0,0 +1,145 @@ +package cacher + +import ( + "fmt" + "io" + "io/ioutil" + "mime" + "net/http" + "crypto/tls" + "path/filepath" + "strings" + "time" + + "github.com/pkg/errors" + + "openreplay/backend/pkg/url/assets" + "openreplay/backend/pkg/storage" +) + +const BODY_LIMIT = 6 * (1 << 20) // 6 Mb +const MAX_CACHE_DEPTH = 5 + +type cacher struct { + timeoutMap *timeoutMap // Concurrency implemented + s3 *storage.S3 // AWS Docs: "These clients are safe to use concurrently." + httpClient *http.Client // Docs: "Clients are safe for concurrent use by multiple goroutines." + rewriter *assets.Rewriter // Read only + Errors chan error +} + +func NewCacher(region string, bucket string, origin string) *cacher { + rewriter := assets.NewRewriter(origin) + return &cacher{ + timeoutMap: newTimeoutMap(), + s3: storage.NewS3(region, bucket), + httpClient: &http.Client{ + Timeout: time.Duration(6) * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + }, + rewriter: rewriter, + Errors: make(chan error), + } +} + +func (c *cacher) cacheURL(requestURL string, sessionID uint64, depth byte, context string, isJS bool) { + if c.timeoutMap.contains(requestURL) { + return + } + c.timeoutMap.add(requestURL) + var cachePath string + if (isJS) { + cachePath = assets.GetCachePathForJS(requestURL) + } else { + cachePath = assets.GetCachePathForAssets(sessionID, requestURL) + } + if c.s3.Exists(cachePath) { + return + } + + req, _ := http.NewRequest("GET", requestURL, nil) + req.Header.Set("Cookie", "ABv=3;") // Hack for rueducommerce + res, err := c.httpClient.Do(req) + if err != nil { + c.Errors <- errors.Wrap(err, context) + return + } + defer res.Body.Close() + if res.StatusCode != 200 { + // TODO: retry + c.Errors <- errors.Wrap(fmt.Errorf("Status code is %v, ", res.StatusCode), context) + return + } + data, err := ioutil.ReadAll(io.LimitReader(res.Body, BODY_LIMIT+1)) + if err != nil { + c.Errors <- errors.Wrap(err, context) + return + } + if len(data) > BODY_LIMIT { + c.Errors <- errors.Wrap(errors.New("Maximum size exceeded"), context) + return + } + + contentType := res.Header.Get("Content-Type") + if contentType == "" { + contentType = mime.TypeByExtension(filepath.Ext(res.Request.URL.Path)) + } + isCSS := strings.HasPrefix(contentType, "text/css") + + strData := string(data) + if isCSS { + strData = c.rewriter.RewriteCSS(sessionID, requestURL, strData) // TODO: one method for reqrite and return list + } + + // TODO: implement in streams + err = c.s3.Upload(strings.NewReader(strData), cachePath, contentType, false) + if err != nil { + c.Errors <- errors.Wrap(err, context) + return + } + c.timeoutMap.add(requestURL) + + if isCSS { + if depth > 0 { + for _, extractedURL := range assets.ExtractURLsFromCSS(string(data)) { + if fullURL, cachable := assets.GetFullCachableURL(requestURL, extractedURL); cachable { + go c.cacheURL(fullURL, sessionID, depth-1, context + "\n -> " + fullURL, false) + } + } + if err != nil { + c.Errors <- errors.Wrap(err, context) + return + } + } else { + c.Errors <- errors.Wrap(errors.New("Maximum recursion cache depth exceeded"), context) + return + } + } + return +} + +func (c *cacher) CacheJSFile(sourceURL string) { + go c.cacheURL(sourceURL, 0, 0, sourceURL, true) +} + +func (c *cacher) CacheURL(sessionID uint64, fullURL string) { + go c.cacheURL(fullURL, sessionID, MAX_CACHE_DEPTH, fullURL, false) +} + +// func (c *cacher) CacheURL(sessionID uint64, baseURL string, relativeURL string) { +// if fullURL, cachable := assets.GetFullCachableURL(baseURL, relativeURL); cachable { +// c.CacheURL(sessionID, fullURL) +// } +// } + +// func (c *cacher) CacheCSSLinks(baseURL string, css string, sessionID uint64) { +// for _, extractedURL := range assets.ExtractURLsFromCSS(css) { +// c.CacheURL(sessionID, baseURL, extractedURL) +// } +// } + +func (c *cacher) UpdateTimeouts() { + c.timeoutMap.deleteOutdated() +} diff --git a/backend/services/assets/cacher/timeoutMap.go b/backend/services/assets/cacher/timeoutMap.go new file mode 100644 index 000000000..36fc4ee4d --- /dev/null +++ b/backend/services/assets/cacher/timeoutMap.go @@ -0,0 +1,45 @@ +package cacher + +import ( + "sync" + "time" +) + +const MAX_STORAGE_TIME = 18 * time.Hour + +// If problem with cache contention (>=4 core) look at sync.Map + +type timeoutMap struct { + mx sync.RWMutex + m map[string]time.Time +} + +func newTimeoutMap() *timeoutMap { + return &timeoutMap{ + m: make(map[string]time.Time), + } +} + +func (tm *timeoutMap) add(key string) { + tm.mx.Lock() + defer tm.mx.Unlock() + tm.m[key] = time.Now() +} + +func (tm *timeoutMap) contains(key string) bool { + tm.mx.RLock() + defer tm.mx.RUnlock() + _, ok := tm.m[key] + return ok +} + +func (tm *timeoutMap) deleteOutdated() { + now := time.Now() + tm.mx.Lock() + defer tm.mx.Unlock() + for key, t := range tm.m { + if now.Sub(t) > MAX_STORAGE_TIME { + delete(tm.m, key) + } + } +} diff --git a/backend/services/assets/jsexception.go b/backend/services/assets/jsexception.go new file mode 100644 index 000000000..ce5852bd5 --- /dev/null +++ b/backend/services/assets/jsexception.go @@ -0,0 +1,32 @@ +package main + +import ( + "encoding/json" + "strings" +) + + +type frame struct { + FileName string `json:"fileName"` +} + + +func extractJSExceptionSources(payload *string) ([]string, error) { + var frameList []frame + err := json.Unmarshal([]byte(*payload), &frameList) + if err != nil { + return nil, err + } + + presentedFileName := make(map[string]bool) + var fileNamesList []string + + for _, f := range frameList { + fn := strings.Split(f.FileName, "?")[0] + if strings.HasPrefix(fn, "http") && !presentedFileName[fn] { + fileNamesList = append(fileNamesList, f.FileName) + presentedFileName[fn] = true + } + } + return fileNamesList, nil +} \ No newline at end of file diff --git a/backend/services/assets/main.go b/backend/services/assets/main.go new file mode 100644 index 000000000..e62c277de --- /dev/null +++ b/backend/services/assets/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "log" + "time" + + "os" + "os/signal" + "syscall" + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/queue/types" + "openreplay/backend/services/assets/cacher" +) + + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + + GROUP_CACHE := env.String("GROUP_CACHE") + TOPIC_TRIGGER := env.String("TOPIC_TRIGGER") + + cacher := cacher.NewCacher( + env.String("AWS_REGION"), + env.String("S3_BUCKET_ASSETS"), + env.String("ASSETS_ORIGIN"), + ) + + consumer := queue.NewMessageConsumer( + GROUP_CACHE, + []string{ TOPIC_TRIGGER }, + func(sessionID uint64, message messages.Message, e *types.Meta) { + switch msg := message.(type) { + case *messages.AssetCache: + cacher.CacheURL(sessionID, msg.URL) + case *messages.ErrorEvent: + if msg.Source != "js_exception" { + return + } + sourceList, err := extractJSExceptionSources(&msg.Payload) + if err != nil { + log.Printf("Error on source extraction: %v", err) + return + } + for _, source := range sourceList { + cacher.CacheJSFile(source) + } + } + }, + ) + + + tick := time.Tick(20 * time.Minute) + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + consumer.Close() + os.Exit(0) + case <-tick: + cacher.UpdateTimeouts() + default: + if err := consumer.ConsumeNext(); err != nil { + log.Fatalf("Error on consumption: %v", err) + } + } + } +} \ No newline at end of file diff --git a/backend/services/db/heuristics/anr.go b/backend/services/db/heuristics/anr.go new file mode 100644 index 000000000..266f882f9 --- /dev/null +++ b/backend/services/db/heuristics/anr.go @@ -0,0 +1,52 @@ +package heuristics + +import ( + . "openreplay/backend/pkg/messages" +) + + +const MIN_TIME_AFTER_LAST_HEARTBEAT = 60 * 1000 + +type anr struct { + readyMessageStore + lastLabel string + lastHeartbeatTimestamp uint64 + lastHeartbeatIndex uint64 +} + +func (h *anr) buildIf(timestamp uint64) { + if h.lastHeartbeatTimestamp != 0 && h.lastHeartbeatTimestamp + MIN_TIME_AFTER_LAST_HEARTBEAT <= timestamp { + m := &IOSIssueEvent{ + Type: "anr", + ContextString: h.lastLabel, + //Context: "{}", + //Payload: fmt.SPrint + } + m.Timestamp = h.lastHeartbeatTimestamp + m.Index = h.lastHeartbeatIndex // Associated Index/ MessageID ? + h.append(m) + h.lastHeartbeatTimestamp = 0 + h.lastHeartbeatIndex = 0 + } +} + +func (h *anr) HandleMessage(msg Message) { + switch m := msg.(type) { + case *IOSClickEvent: + h.buildIf(m.Timestamp) + h.lastLabel = m.Label + h.lastHeartbeatTimestamp = m.Timestamp + h.lastHeartbeatIndex = m.Index + case *IOSInputEvent: + h.buildIf(m.Timestamp) + h.lastLabel = m.Label + h.lastHeartbeatTimestamp = m.Timestamp + h.lastHeartbeatIndex = m.Index + case *IOSPerformanceEvent: + h.buildIf(m.Timestamp) + h.lastHeartbeatTimestamp = m.Timestamp + h.lastHeartbeatIndex = m.Index + case *IOSSessionEnd: + h.buildIf(m.Timestamp) + } +} \ No newline at end of file diff --git a/backend/services/db/heuristics/clickrage.go b/backend/services/db/heuristics/clickrage.go new file mode 100644 index 000000000..4dc86ee65 --- /dev/null +++ b/backend/services/db/heuristics/clickrage.go @@ -0,0 +1,58 @@ +package heuristics + +import ( + . "openreplay/backend/pkg/messages" +) + + +const CLICK_TIME_DIFF = 200 +const MIN_CLICKS_IN_A_ROW = 3 + +type clickrage struct { + readyMessageStore + lastTimestamp uint64 + lastLabel string + firstInARawTimestamp uint64 + firstInARawSeqIndex uint64 + countsInARow int +} + +func (h *clickrage) build() { + if h.countsInARow >= MIN_CLICKS_IN_A_ROW { + m := &IOSIssueEvent{ + Type: "click_rage", + ContextString: h.lastLabel, + //Context: "{}", + //Payload: fmt.SPrint + } + m.Timestamp = h.firstInARawTimestamp + m.Index = h.firstInARawSeqIndex // Associated Index/ MessageID ? + h.append(m) + } + h.lastTimestamp = 0 + h.lastLabel = "" + h.firstInARawTimestamp = 0 + h.firstInARawSeqIndex = 0 + h.countsInARow = 0 +} + +func (h *clickrage) HandleMessage(msg Message) { + switch m := msg.(type) { + case *IOSClickEvent: + if h.lastTimestamp + CLICK_TIME_DIFF < m.Timestamp && h.lastLabel == m.Label { + h.lastTimestamp = m.Timestamp + h.countsInARow += 1 + return + } + h.build() + if m.Label != "" { + h.lastTimestamp = m.Timestamp + h.lastLabel = m.Label + h.firstInARawTimestamp = m.Timestamp + h.firstInARawSeqIndex = m.Index + h.countsInARow = 1 + } + case *IOSSessionEnd: + h.build() + } +} \ No newline at end of file diff --git a/backend/services/db/heuristics/heuristics.go b/backend/services/db/heuristics/heuristics.go new file mode 100644 index 000000000..7832e0a82 --- /dev/null +++ b/backend/services/db/heuristics/heuristics.go @@ -0,0 +1,65 @@ +package heuristics + +import ( + . "openreplay/backend/pkg/messages" + . "openreplay/backend/pkg/db/types" +) + +type MessageHandler interface { + HandleMessage(Message) +} +type ReadyMessagesIterator interface { + IterateReadyMessages(func(Message)) +} + +type Handler interface { + MessageHandler + ReadyMessagesIterator +} + +type mainHandler map[uint64]*sessHandler + + +func NewHandler() mainHandler { + return make(mainHandler) +} + +func (m mainHandler) getSessHandler(session *Session) *sessHandler { + if session == nil { + //AAAA + return nil + } + s := m[session.SessionID] + if s == nil { + s = newSessHandler(session) + m[session.SessionID] = s + } + return s +} + +func (m mainHandler) HandleMessage(session *Session, msg Message) { + s := m.getSessHandler(session) + s.HandleMessage(msg) +} + +func (m mainHandler) IterateSessionReadyMessages(sessionID uint64, iter func(msg Message)) { + s, ok := m[ sessionID ] + if !ok { return } + s.IterateReadyMessages(iter) + if s.IsEnded() { + delete(m, sessionID) + } +} + +func (m mainHandler) IterateReadyMessages(iter func(sessionID uint64, msg Message)) { + for sessionID, s := range m { + s.IterateReadyMessages(func(msg Message) { + iter(sessionID, msg) + }) + if s.IsEnded() { + delete(m, sessionID) + } + } +} + + diff --git a/backend/services/db/heuristics/performance.go b/backend/services/db/heuristics/performance.go new file mode 100644 index 000000000..931d831e6 --- /dev/null +++ b/backend/services/db/heuristics/performance.go @@ -0,0 +1,103 @@ +package heuristics + +import ( + . "openreplay/backend/pkg/messages" +) + + +const AGGR_TIME = 15 * 60 * 1000 + + +type valueAggregator struct { + sum float64 + count float64 +} +func (va *valueAggregator) aggregate() uint64 { + if va.count == 0 { + return 0 + } + return uint64(va.sum/va.count) +} + +type performanceAggregator struct { + readyMessageStore + pa *IOSPerformanceAggregated + fps valueAggregator + cpu valueAggregator + memory valueAggregator + battery valueAggregator +} + +func (h *performanceAggregator) build(timestamp uint64) { + if h.pa == nil { + return + } + h.pa.TimestampEnd = timestamp + h.pa.AvgFPS = h.fps.aggregate() + h.pa.AvgCPU = h.cpu.aggregate() + h.pa.AvgMemory = h.memory.aggregate() + h.pa.AvgBattery = h.battery.aggregate() + + h.append(h.pa) + + h.pa = &IOSPerformanceAggregated{} + for _, agg := range []valueAggregator{h.fps, h.cpu, h.memory, h.battery} { + agg.sum = 0 + agg.count = 0 + } +} + +func (h *performanceAggregator) HandleMessage(msg Message) { + if h.pa == nil { + h.pa = &IOSPerformanceAggregated{} // TODO: struct type in messages + } + switch m := msg.(type) { // TODO: All Timestampe messages + case *IOSPerformanceEvent: + if h.pa.TimestampStart == 0 { + h.pa.TimestampStart = m.Timestamp + } + if h.pa.TimestampStart + AGGR_TIME <= m.Timestamp { + h.build(m.Timestamp) + } + switch m.Name { + case "fps": + h.fps.count += 1 + h.fps.sum += float64(m.Value) + if m.Value < h.pa.MinFPS || h.pa.MinFPS == 0 { + h.pa.MinFPS = m.Value + } + if m.Value > h.pa.MaxFPS { + h.pa.MaxFPS = m.Value + } + case "mainThreadCPU": + h.cpu.count += 1 + h.cpu.sum += float64(m.Value) + if m.Value < h.pa.MinCPU || h.pa.MinCPU == 0 { + h.pa.MinCPU = m.Value + } + if m.Value > h.pa.MaxCPU { + h.pa.MaxCPU = m.Value + } + case "memoryUsage": + h.memory.count += 1 + h.memory.sum += float64(m.Value) + if m.Value < h.pa.MinMemory || h.pa.MinMemory == 0 { + h.pa.MinMemory = m.Value + } + if m.Value > h.pa.MaxMemory { + h.pa.MaxMemory = m.Value + } + case "batteryLevel": + h.battery.count += 1 + h.battery.sum += float64(m.Value) + if m.Value < h.pa.MinBattery || h.pa.MinBattery == 0 { + h.pa.MinBattery = m.Value + } + if m.Value > h.pa.MaxBattery { + h.pa.MaxBattery = m.Value + } + } + case *IOSSessionEnd: + h.build(m.Timestamp) + } +} \ No newline at end of file diff --git a/backend/services/db/heuristics/readyMessageStore.go b/backend/services/db/heuristics/readyMessageStore.go new file mode 100644 index 000000000..9c619e20b --- /dev/null +++ b/backend/services/db/heuristics/readyMessageStore.go @@ -0,0 +1,21 @@ +package heuristics + +import ( + . "openreplay/backend/pkg/messages" +) + + +type readyMessageStore struct { + store []Message +} + +func (s *readyMessageStore) append(msg Message) { + s.store = append(s.store, msg) +} + +func (s *readyMessageStore) IterateReadyMessages(cb func(msg Message)) { + for _, msg := range s.store { + cb(msg) + } + s.store = nil +} \ No newline at end of file diff --git a/backend/services/db/heuristics/session.go b/backend/services/db/heuristics/session.go new file mode 100644 index 000000000..d828ca478 --- /dev/null +++ b/backend/services/db/heuristics/session.go @@ -0,0 +1,47 @@ +package heuristics + +import ( + . "openreplay/backend/pkg/messages" + . "openreplay/backend/pkg/db/types" +) + + +type sessHandler struct { + session *Session + handlers []Handler + ended bool +} + + +func newSessHandler(session *Session) *sessHandler { + return &sessHandler{ + session: session, + handlers: []Handler{ + new(clickrage), + new(performanceAggregator), + new(anr), + }, + } +} + +func (s *sessHandler) HandleMessage(msg Message) { + for _, h := range s.handlers { + h.HandleMessage(msg) + } + if _, isEnd := msg.(*IOSSessionEnd); isEnd { + s.ended = true + } + if _, isEnd := msg.(*SessionEnd); isEnd { + s.ended = true + } +} + +func (s *sessHandler) IterateReadyMessages(cb func(msg Message)) { + for _, h := range s.handlers { + h.IterateReadyMessages(cb) + } +} + +func (s *sessHandler) IsEnded() bool { + return s.ended +} \ No newline at end of file diff --git a/backend/services/db/main.go b/backend/services/db/main.go new file mode 100644 index 000000000..bd5c254e2 --- /dev/null +++ b/backend/services/db/main.go @@ -0,0 +1,97 @@ +package main + +import ( + "log" + "time" + + "os" + "os/signal" + "syscall" + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/queue/types" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/pkg/db/cache" + "openreplay/backend/services/db/heuristics" +) + + +var pg *cache.PGCache + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + + initStats() + pg = cache.NewPGCache(postgres.NewConn(env.String("POSTGRES_STRING")), 1000 * 60 * 20) + defer pg.Close() + + heurFinder := heuristics.NewHandler() + + consumer := queue.NewMessageConsumer( + env.String("GROUP_DB"), + []string{ + //env.String("TOPIC_RAW"), + env.String("TOPIC_TRIGGER"), + }, + func(sessionID uint64, msg messages.Message, _ *types.Meta) { + if err := insertMessage(sessionID, msg); err != nil { + if !postgres.IsPkeyViolation(err) { + log.Printf("Message Insertion Error %v, Message %v", err, msg) + } + return + } + + session, err := pg.GetSession(sessionID) + if err != nil { + // Might happen due to the assets-related message TODO: log only if session is necessary for this kind of message + log.Printf("Error on session retrieving from cache: %v, Message %v, sessionID %v", err, msg, sessionID) + return; + } + + err = insertStats(session, msg) + if err != nil { + log.Printf("Stats Insertion Error %v; Session:%v, Message: %v", err, session, msg) + } + + heurFinder.HandleMessage(session, msg) + heurFinder.IterateSessionReadyMessages(sessionID, func(msg messages.Message) { + // TODO: DRY code (carefully with the return statement logic) + if err := insertMessage(sessionID, msg); err != nil { + if !postgres.IsPkeyViolation(err) { + log.Printf("Message Insertion Error %v, Message %v", err, msg) + } + return + } + + err = insertStats(session, msg) + if err != nil { + log.Printf("Stats Insertion Error %v", err) + } + }) + }, + ) + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + tick := time.Tick(15 * time.Second) + + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + consumer.Close() + os.Exit(0) + case <-tick: + commitStats() // TODO: sync with wueue commit + default: + err := consumer.ConsumeNext() + if err != nil { + log.Fatalf("Error on consumption: %v", err) // TODO: is always fatal? + } + } + } + +} \ No newline at end of file diff --git a/backend/services/db/messages.go b/backend/services/db/messages.go new file mode 100644 index 000000000..6aa4ac076 --- /dev/null +++ b/backend/services/db/messages.go @@ -0,0 +1,64 @@ +package main + +import ( + . "openreplay/backend/pkg/messages" +) + +func insertMessage(sessionID uint64, msg Message) error { + switch m := msg.(type) { + // Common + case *Metadata: + return pg.InsertMetadata(sessionID, m) + case *IssueEvent: + return pg.InsertIssueEvent(sessionID, m) + //TODO: message adapter (transformer) (at the level of pkg/message) for types: + // case *IOSMetadata, *IOSIssueEvent and others + + // Web + case *SessionStart: + return pg.InsertWebSessionStart(sessionID, m) + case *SessionEnd: + return pg.InsertWebSessionEnd(sessionID, m) + case *UserID: + return pg.InsertWebUserID(sessionID, m) + case *UserAnonymousID: + return pg.InsertWebUserAnonymousID(sessionID, m) + case *CustomEvent: + return pg.InsertWebCustomEvent(sessionID, m) + case *ClickEvent: + return pg.InsertWebClickEvent(sessionID, m) + case *InputEvent: + return pg.InsertWebInputEvent(sessionID, m) + // Unique Web messages + case *ResourceEvent: + return pg.InsertWebResourceEvent(sessionID, m) + case *PageEvent: + return pg.InsertWebPageEvent(sessionID, m) + case *ErrorEvent: + return pg.InsertWebErrorEvent(sessionID, m) + + // IOS + case *IOSSessionStart: + return pg.InsertIOSSessionStart(sessionID, m) + case *IOSSessionEnd: + return pg.InsertIOSSessionEnd(sessionID, m) + case *IOSUserID: + return pg.InsertIOSUserID(sessionID, m) + case *IOSUserAnonymousID: + return pg.InsertIOSUserAnonymousID(sessionID, m) + case *IOSCustomEvent: + return pg.InsertIOSCustomEvent(sessionID, m) + case *IOSClickEvent: + return pg.InsertIOSClickEvent(sessionID, m) + case *IOSInputEvent: + return pg.InsertIOSInputEvent(sessionID, m) + // Unique IOS messages + case *IOSNetworkCall: + return pg.InsertIOSNetworkCall(sessionID, m) + case *IOSScreenEnter: + return pg.InsertIOSScreenEnter(sessionID, m) + case *IOSCrash: + return pg.InsertIOSCrash(sessionID, m) + } + return nil // "Not implemented" +} \ No newline at end of file diff --git a/backend/services/db/stats.go b/backend/services/db/stats.go new file mode 100644 index 000000000..81abf1b91 --- /dev/null +++ b/backend/services/db/stats.go @@ -0,0 +1,35 @@ +package main + +import ( + + . "openreplay/backend/pkg/messages" + . "openreplay/backend/pkg/db/types" +) + +func initStats() { + // noop +} + + +func insertStats(session *Session, msg Message) error { + switch m := msg.(type) { + // Web + case *PerformanceTrackAggr: + return pg.InsertWebStatsPerformance(session.SessionID, m) + case *ResourceEvent: + return pg.InsertWebStatsResourceEvent(session.SessionID, m) + case *LongTask: + return pg.InsertWebStatsLongtask(session.SessionID, m) + + // IOS + // case *IOSPerformanceAggregated: + // return pg.InsertIOSPerformanceAggregated(session, m) + // case *IOSNetworkCall: + // return pg.InsertIOSNetworkCall(session, m) + } + return nil +} + +func commitStats() error { + return nil +} diff --git a/backend/services/ender/builder/builder.go b/backend/services/ender/builder/builder.go new file mode 100644 index 000000000..49fbd9443 --- /dev/null +++ b/backend/services/ender/builder/builder.go @@ -0,0 +1,316 @@ +package builder + +import ( + "net/url" + "strings" + + "log" + + "openreplay/backend/pkg/intervals" + . "openreplay/backend/pkg/messages" +) + +func getURLExtention(URL string) string { + u, err := url.Parse(URL) + if err != nil { + return "" + } + i := strings.LastIndex(u.Path, ".") + return u.Path[i+1:] +} + +func getResourceType(initiator string, URL string) string { + switch initiator { + case "xmlhttprequest", "fetch": + return "fetch" + case "img": + return "img" + default: + switch getURLExtention(URL) { + case "css": + return "stylesheet" + case "js": + return "script" + case "png", "gif", "jpg", "jpeg", "svg": + return "img" + case "mp4", "mkv", "ogg", "webm", "avi", "mp3": + return "media" + default: + return "other" + } + } +} + +type builder struct { + readyMsgs []Message + timestamp uint64 + peBuilder *pageEventBuilder + ptaBuilder *performanceTrackAggrBuilder + ieBuilder *inputEventBuilder + ciFinder *cpuIssueFinder + miFinder *memoryIssueFinder + ddDetector *domDropDetector + crDetector *clickRageDetector + dcDetector *deadClickDetector + integrationsWaiting bool + + + sid uint64 +} + +func NewBuilder() *builder { + return &builder{ + peBuilder: &pageEventBuilder{}, + ptaBuilder: &performanceTrackAggrBuilder{}, + ieBuilder: NewInputEventBuilder(), + ciFinder: &cpuIssueFinder{}, + miFinder: &memoryIssueFinder{}, + ddDetector: &domDropDetector{}, + crDetector: &clickRageDetector{}, + dcDetector: &deadClickDetector{}, + integrationsWaiting: true, + } +} + +func (b *builder) appendReadyMessage(msg Message) { // interface is never nil even if it holds nil value + b.readyMsgs = append(b.readyMsgs, msg) +} + +func (b *builder) iterateReadyMessage(iter func(msg Message)) { + for _, readyMsg := range b.readyMsgs { + iter(readyMsg) + } + b.readyMsgs = nil +} + +func (b *builder) buildSessionEnd() { + sessionEnd := &SessionEnd{ + Timestamp: b.timestamp, // + delay? + } + b.appendReadyMessage(sessionEnd) +} + +func (b *builder) buildPageEvent() { + if msg := b.peBuilder.Build(); msg != nil { + b.appendReadyMessage(msg) + } +} +func (b *builder) buildPerformanceTrackAggr() { + if msg := b.ptaBuilder.Build(); msg != nil { + b.appendReadyMessage(msg) + } +} +func (b *builder) buildInputEvent() { + if msg := b.ieBuilder.Build(); msg != nil { + b.appendReadyMessage(msg) + } +} + +func (b *builder) handleMessage(message Message, messageID uint64) { + timestamp := uint64(message.Meta().Timestamp) + if b.timestamp <= timestamp { + b.timestamp = timestamp + } + // Start from the first timestamp. + switch msg := message.(type) { + case *SessionStart, + *Metadata, + *UserID, + *UserAnonymousID: + b.appendReadyMessage(msg) + } + if b.timestamp == 0 { + return + } + switch msg := message.(type) { + case *SetPageLocation: + if msg.NavigationStart == 0 { + b.appendReadyMessage(&PageEvent{ + URL: msg.URL, + Referrer: msg.Referrer, + Loaded: false, + MessageID: messageID, + Timestamp: b.timestamp, + }) + } else { + b.buildPageEvent() + b.buildInputEvent() + b.ieBuilder.ClearLabels() + b.peBuilder.HandleSetPageLocation(msg, messageID, b.timestamp) + b.miFinder.HandleSetPageLocation(msg) + b.ciFinder.HandleSetPageLocation(msg) + } + case *PageLoadTiming: + if rm := b.peBuilder.HandlePageLoadTiming(msg); rm != nil { + b.appendReadyMessage(rm) + } + case *PageRenderTiming: + if rm := b.peBuilder.HandlePageRenderTiming(msg); rm != nil { + b.appendReadyMessage(rm) + } + case *PerformanceTrack: + if rm := b.ptaBuilder.HandlePerformanceTrack(msg, b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } + if rm := b.ciFinder.HandlePerformanceTrack(msg, messageID, b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } + if rm := b.miFinder.HandlePerformanceTrack(msg, messageID, b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } + case *SetInputTarget: + if rm := b.ieBuilder.HandleSetInputTarget(msg); rm != nil { + b.appendReadyMessage(rm) + } + case *SetInputValue: + if rm := b.ieBuilder.HandleSetInputValue(msg, messageID, b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } + case *MouseClick: + b.buildInputEvent() + if rm := b.crDetector.HandleMouseClick(msg, messageID, b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } + if msg.Label != "" { + b.appendReadyMessage(&ClickEvent{ + MessageID: messageID, + Label: msg.Label, + HesitationTime: msg.HesitationTime, + Timestamp: b.timestamp, + }) + } + case *RawErrorEvent: + b.appendReadyMessage(&ErrorEvent{ + MessageID: messageID, + Timestamp: msg.Timestamp, + Source: msg.Source, + Name: msg.Name, + Message: msg.Message, + Payload: msg.Payload, + }) + case *JSException: + b.appendReadyMessage(&ErrorEvent{ + MessageID: messageID, + Timestamp: b.timestamp, + Source: "js_exception", + Name: msg.Name, + Message: msg.Message, + Payload: msg.Payload, + }) + case *ResourceTiming: + tp := getResourceType(msg.Initiator, msg.URL) + success := msg.Duration != 0 + b.appendReadyMessage(&ResourceEvent{ + MessageID: messageID, + Timestamp: msg.Timestamp, + Duration: msg.Duration, + TTFB: msg.TTFB, + HeaderSize: msg.HeaderSize, + EncodedBodySize: msg.EncodedBodySize, + DecodedBodySize: msg.DecodedBodySize, + URL: msg.URL, + Type: tp, + Success: success, + }) + if !success && tp == "fetch" { + b.appendReadyMessage(&IssueEvent{ + Type: "bad_request", + MessageID: messageID, + Timestamp: msg.Timestamp, + ContextString: msg.URL, + Context: "", + Payload: "", + }) + } + case *RawCustomEvent: + b.appendReadyMessage(&CustomEvent{ + MessageID: messageID, + Timestamp: b.timestamp, + Name: msg.Name, + Payload: msg.Payload, + }) + case *CustomIssue: + b.appendReadyMessage(&IssueEvent{ + Type: "custom", + Timestamp: b.timestamp, + MessageID: messageID, + ContextString: msg.Name, + Payload: msg.Payload, + }) + case *Fetch: + b.appendReadyMessage(&ResourceEvent{ + MessageID: messageID, + Timestamp: msg.Timestamp, + Duration: msg.Duration, + URL: msg.URL, + Type: "fetch", + Success: msg.Status < 300, + Method: msg.Method, + Status: msg.Status, + }) + case *StateAction: + b.appendReadyMessage(&StateActionEvent{ + MessageID: messageID, + Timestamp: b.timestamp, + Type: msg.Type, + }) + case *GraphQL: + b.appendReadyMessage(&GraphQLEvent{ + MessageID: messageID, + Timestamp: b.timestamp, + Name: msg.OperationName, + }) + case *CreateElementNode, + *CreateTextNode: + b.ddDetector.HandleNodeCreation() + case *RemoveNode: + b.ddDetector.HandleNodeRemoval(b.timestamp) + case *CreateDocument: + if rm := b.ddDetector.Build(); rm != nil { + b.appendReadyMessage(rm) + } + } + if rm := b.dcDetector.HandleMessage(message, messageID, b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } +} + + +func (b *builder) checkTimeouts(ts int64) bool { + if b.timestamp == 0 { + return false // There was no timestamp events yet + } + + if b.peBuilder.HasInstance() && int64(b.peBuilder.GetTimestamp())+intervals.EVENTS_PAGE_EVENT_TIMEOUT < ts { + b.buildPageEvent() + } + if b.ieBuilder.HasInstance() && int64(b.ieBuilder.GetTimestamp())+intervals.EVENTS_INPUT_EVENT_TIMEOUT < ts { + b.buildInputEvent() + } + if b.ptaBuilder.HasInstance() && int64(b.ptaBuilder.GetStartTimestamp())+intervals.EVENTS_PERFORMANCE_AGGREGATION_TIMEOUT < ts { + b.buildPerformanceTrackAggr() + } + + lastTsGap := ts - int64(b.timestamp) + //log.Printf("checking timeouts for sess %v: %v now, %v sesstime; gap %v",b.sid, ts, b.timestamp, lastTsGap) + if lastTsGap > intervals.EVENTS_SESSION_END_TIMEOUT { + if rm := b.ddDetector.Build(); rm != nil { + b.appendReadyMessage(rm) + } + if rm := b.ciFinder.Build(); rm != nil { + b.appendReadyMessage(rm) + } + if rm := b.miFinder.Build(); rm != nil { + b.appendReadyMessage(rm) + } + if rm := b.crDetector.Build(); rm != nil { + b.appendReadyMessage(rm) + } + if rm := b.dcDetector.HandleReaction(b.timestamp); rm != nil { + b.appendReadyMessage(rm) + } + b.buildSessionEnd() + return true + } + return false +} diff --git a/backend/services/ender/builder/builderMap.go b/backend/services/ender/builder/builderMap.go new file mode 100644 index 000000000..6ab3c3ac7 --- /dev/null +++ b/backend/services/ender/builder/builderMap.go @@ -0,0 +1,52 @@ +package builder + +import ( + . "openreplay/backend/pkg/messages" +) + +type builderMap map[uint64]*builder + + +func NewBuilderMap() builderMap { + return make(builderMap) +} + +func (m builderMap) GetBuilder(sessionID uint64) *builder { + b := m[sessionID] + if b == nil { + b = NewBuilder() + m[sessionID] = b + b.sid = sessionID + + } + return b +} + +func (m builderMap) HandleMessage(sessionID uint64, msg Message, messageID uint64) { + b := m.GetBuilder(sessionID) + b.handleMessage(msg, messageID) +} + +func (m builderMap) IterateSessionReadyMessages(sessionID uint64, operatingTs int64, iter func(msg Message)) { + b, ok := m[ sessionID ] + if !ok { return } + sessionEnded := b.checkTimeouts(operatingTs) + b.iterateReadyMessage(iter) + if sessionEnded { + delete(m, sessionID) + } +} + +func (m builderMap) IterateReadyMessages(operatingTs int64, iter func(sessionID uint64, msg Message)) { + for sessionID, b := range m { + sessionEnded := b.checkTimeouts(operatingTs) + b.iterateReadyMessage(func(msg Message) { + iter(sessionID, msg) + }) + if sessionEnded { + delete(m, sessionID) + } + } +} + + diff --git a/backend/services/ender/builder/clikRageDetector.go b/backend/services/ender/builder/clikRageDetector.go new file mode 100644 index 000000000..318f9f26f --- /dev/null +++ b/backend/services/ender/builder/clikRageDetector.go @@ -0,0 +1,57 @@ +package builder + +import ( + "encoding/json" + + . "openreplay/backend/pkg/messages" +) + + +const CLICK_TIME_DIFF = 200 +const MIN_CLICKS_IN_A_ROW = 3 + +type clickRageDetector struct { + lastTimestamp uint64 + lastLabel string + firstInARawTimestamp uint64 + firstInARawMessageId uint64 + countsInARow int +} + + +func (crd *clickRageDetector) Build() *IssueEvent { + var i *IssueEvent + if crd.countsInARow >= MIN_CLICKS_IN_A_ROW { + payload, _ := json.Marshal(struct{Count int }{crd.countsInARow,}) + i = &IssueEvent{ + Type: "click_rage", + ContextString: crd.lastLabel, + Payload: string(payload), // TODO: json encoder + Timestamp: crd.firstInARawTimestamp, + MessageID: crd.firstInARawMessageId, + } + } + crd.lastTimestamp = 0 + crd.lastLabel = "" + crd.firstInARawTimestamp = 0 + crd.firstInARawMessageId = 0 + crd.countsInARow = 0 + return i +} + +func (crd *clickRageDetector) HandleMouseClick(msg *MouseClick, messageID uint64, timestamp uint64) *IssueEvent { + if crd.lastTimestamp + CLICK_TIME_DIFF < timestamp && crd.lastLabel == msg.Label { + crd.lastTimestamp = timestamp + crd.countsInARow += 1 + return nil + } + i := crd.Build() + if msg.Label != "" { + crd.lastTimestamp = timestamp + crd.lastLabel = msg.Label + crd.firstInARawTimestamp = timestamp + crd.firstInARawMessageId = messageID + crd.countsInARow = 1 + } + return i +} \ No newline at end of file diff --git a/backend/services/ender/builder/cpuIssueFinder.go b/backend/services/ender/builder/cpuIssueFinder.go new file mode 100644 index 000000000..be02c280f --- /dev/null +++ b/backend/services/ender/builder/cpuIssueFinder.go @@ -0,0 +1,86 @@ +package builder + +import ( + "encoding/json" + + "openreplay/backend/pkg/messages/performance" + . "openreplay/backend/pkg/messages" +) + +const CPU_THRESHOLD = 70 // % out of 100 +const CPU_MIN_DURATION_TRIGGER = 6 * 1000 + + +type cpuIssueFinder struct { + startTimestamp uint64 + startMessageID uint64 + lastTimestamp uint64 + maxRate uint64 + contextString string +} + +func (f *cpuIssueFinder) Build() *IssueEvent { + if f.startTimestamp == 0 { + return nil + } + duration := f.lastTimestamp - f.startTimestamp + timestamp := f.startTimestamp + messageID := f.startMessageID + maxRate := f.maxRate + + f.startTimestamp = 0 + f.startMessageID = 0 + f.maxRate = 0 + if duration < CPU_MIN_DURATION_TRIGGER { + return nil + } + + payload, _ := json.Marshal(struct{ + Duration uint64 + Rate uint64 + }{duration,maxRate}) + return &IssueEvent{ + Type: "cpu", + Timestamp: timestamp, + MessageID: messageID, + ContextString: f.contextString, + Payload: string(payload), + } +} + +func (f *cpuIssueFinder) HandleSetPageLocation(msg *SetPageLocation) { + f.contextString = msg.URL +} + + + +func (f *cpuIssueFinder) HandlePerformanceTrack(msg *PerformanceTrack, messageID uint64, timestamp uint64) *IssueEvent { + dt := performance.TimeDiff(timestamp, f.lastTimestamp) + if dt == 0 { + return nil // TODO: handle error + } + + f.lastTimestamp = timestamp + + if msg.Frames == -1 || msg.Ticks == -1 { + return f.Build() + } + + cpuRate := performance.CPURate(msg.Ticks, dt) + + if cpuRate >= CPU_THRESHOLD { + if f.startTimestamp == 0 { + f.startTimestamp = timestamp + f.startMessageID = messageID + } + if f.maxRate < cpuRate { + f.maxRate = cpuRate + } + } else { + return f.Build() + } + + return nil +} + + diff --git a/backend/services/ender/builder/deadClickDetector.go b/backend/services/ender/builder/deadClickDetector.go new file mode 100644 index 000000000..a34a9b08b --- /dev/null +++ b/backend/services/ender/builder/deadClickDetector.go @@ -0,0 +1,55 @@ +package builder + +import ( + . "openreplay/backend/pkg/messages" +) + + +const CLICK_RELATION_TIME = 1400 + +type deadClickDetector struct { + lastMouseClick *MouseClick + lastTimestamp uint64 + lastMessageID uint64 +} + + +func (d *deadClickDetector) HandleReaction(timestamp uint64) *IssueEvent { + var i *IssueEvent + if d.lastMouseClick != nil && d.lastTimestamp + CLICK_RELATION_TIME < timestamp { + i = &IssueEvent{ + Type: "dead_click", + ContextString: d.lastMouseClick.Label, + Timestamp: d.lastTimestamp, + MessageID: d.lastMessageID, + } + } + d.lastMouseClick = nil + d.lastTimestamp = 0 + d.lastMessageID = 0 + return i +} + +func (d *deadClickDetector) HandleMessage(msg Message, messageID uint64, timestamp uint64) *IssueEvent { + var i *IssueEvent + switch m := msg.(type) { + case *MouseClick: + i = d.HandleReaction(timestamp) + d.lastMouseClick = m + d.lastTimestamp = timestamp + d.lastMessageID = messageID + case *SetNodeAttribute, + *RemoveNodeAttribute, + *CreateElementNode, + *CreateTextNode, + *MoveNode, + *RemoveNode, + *SetCSSData, + *CSSInsertRule, + *CSSDeleteRule: + i = d.HandleReaction(timestamp) + } + return i +} + + diff --git a/backend/services/ender/builder/domDropDetector.go b/backend/services/ender/builder/domDropDetector.go new file mode 100644 index 000000000..3366a0163 --- /dev/null +++ b/backend/services/ender/builder/domDropDetector.go @@ -0,0 +1,42 @@ +package builder + +import ( + . "openreplay/backend/pkg/messages" +) + + +type domDropDetector struct { + removedCount int + lastDropTimestamp uint64 +} + +const DROP_WINDOW = 200 //ms +const CRITICAL_COUNT = 1 // Our login page contains 20. But on crush it removes only roots (1-3 nodes). + +func (dd *domDropDetector) HandleNodeCreation() { + dd.removedCount = 0 + dd.lastDropTimestamp = 0 +} + +func (dd *domDropDetector) HandleNodeRemoval(ts uint64) { + if dd.lastDropTimestamp + DROP_WINDOW > ts { + dd.removedCount += 1 + } else { + dd.removedCount = 1 + } + dd.lastDropTimestamp = ts +} + + +func (dd *domDropDetector) Build() *DOMDrop { + var domDrop *DOMDrop + if dd.removedCount >= CRITICAL_COUNT { + domDrop = &DOMDrop{ + Timestamp: dd.lastDropTimestamp, + } + } + dd.removedCount = 0 + dd.lastDropTimestamp = 0 + return domDrop +} + diff --git a/backend/services/ender/builder/inputEventBuilder.go b/backend/services/ender/builder/inputEventBuilder.go new file mode 100644 index 000000000..4938e47a9 --- /dev/null +++ b/backend/services/ender/builder/inputEventBuilder.go @@ -0,0 +1,80 @@ +package builder + +import ( + . "openreplay/backend/pkg/messages" +) + +type inputLabels map[uint64]string + +type inputEventBuilder struct { + inputEvent *InputEvent + inputLabels inputLabels + inputID uint64 +} + +func NewInputEventBuilder() *inputEventBuilder { + ieBuilder := &inputEventBuilder{} + ieBuilder.ClearLabels() + return ieBuilder +} + + +func (b *inputEventBuilder) ClearLabels() { + b.inputLabels = make(inputLabels) +} + +func (b *inputEventBuilder) HandleSetInputTarget(msg *SetInputTarget) *InputEvent { + var inputEvent *InputEvent + if b.inputID != msg.ID { + inputEvent = b.Build() + b.inputID = msg.ID + } + b.inputLabels[msg.ID] = msg.Label + return inputEvent +} + +func (b *inputEventBuilder) HandleSetInputValue(msg *SetInputValue, messageID uint64, timestamp uint64) *InputEvent { + var inputEvent *InputEvent + if b.inputID != msg.ID { + inputEvent = b.Build() + b.inputID = msg.ID + } + if b.inputEvent == nil { + b.inputEvent = &InputEvent{ + MessageID: messageID, + Timestamp: timestamp, + Value: msg.Value, + ValueMasked: msg.Mask > 0, + } + } else { + b.inputEvent.Value = msg.Value + b.inputEvent.ValueMasked = msg.Mask > 0 + } + return inputEvent +} + +func (b *inputEventBuilder) HasInstance() bool { + return b.inputEvent != nil +} + +func (b * inputEventBuilder) GetTimestamp() uint64 { + if b.inputEvent == nil { + return 0 + } + return b.inputEvent.Timestamp; +} + +func (b *inputEventBuilder) Build() *InputEvent { + if b.inputEvent == nil { + return nil + } + inputEvent := b.inputEvent + label := b.inputLabels[b.inputID] + // if !ok { + // return nil + // } + inputEvent.Label = label + + b.inputEvent = nil + return inputEvent +} diff --git a/backend/services/ender/builder/memoryIssueFinder.go b/backend/services/ender/builder/memoryIssueFinder.go new file mode 100644 index 000000000..a2702e505 --- /dev/null +++ b/backend/services/ender/builder/memoryIssueFinder.go @@ -0,0 +1,72 @@ +package builder + +import ( + "math" + "encoding/json" + + . "openreplay/backend/pkg/messages" +) + +const MIN_COUNT = 3 +const MEM_RATE_THRESHOLD = 300 // % to average + +type memoryIssueFinder struct { + startMessageID uint64 + startTimestamp uint64 + rate int + count float64 + sum float64 + contextString string +} + +func (f *memoryIssueFinder) Build() *IssueEvent { + if f.startTimestamp == 0 { + return nil + } + payload, _ := json.Marshal(struct{Rate int }{f.rate - 100,}) + i := &IssueEvent{ + Type: "memory", + Timestamp: f.startTimestamp, + MessageID: f.startMessageID, + ContextString: f.contextString, + Payload: string(payload), + } + f.startTimestamp = 0 + f.startMessageID = 0 + f.rate = 0 + return i +} + +func (f *memoryIssueFinder) HandleSetPageLocation(msg *SetPageLocation) { + f.contextString = msg.URL +} + +func (f *memoryIssueFinder) HandlePerformanceTrack(msg *PerformanceTrack, messageID uint64, timestamp uint64) *IssueEvent { + if f.count < MIN_COUNT { + f.sum += float64(msg.UsedJSHeapSize) + f.count++ + return nil + } + + average := f.sum/f.count + rate := int(math.Round(float64(msg.UsedJSHeapSize)/average * 100)) + + f.sum += float64(msg.UsedJSHeapSize) + f.count++ + + if rate >= MEM_RATE_THRESHOLD { + if f.startTimestamp == 0 { + f.startTimestamp = timestamp + f.startMessageID = messageID + } + if f.rate < rate { + f.rate = rate + } + } else { + return f.Build() + } + + return nil +} + + diff --git a/backend/services/ender/builder/pageEventBuilder.go b/backend/services/ender/builder/pageEventBuilder.go new file mode 100644 index 000000000..db602a996 --- /dev/null +++ b/backend/services/ender/builder/pageEventBuilder.go @@ -0,0 +1,91 @@ +package builder + +import ( + . "openreplay/backend/pkg/messages" +) + +type pageEventBuilder struct { + pageEvent *PageEvent + firstTimingHandled bool +} + +func (b *pageEventBuilder) buildIfTimingsComplete() *PageEvent { + if b.firstTimingHandled { + return b.Build() + } + b.firstTimingHandled = true + return nil +} + +// Only for Loaded: true +func (b *pageEventBuilder) HandleSetPageLocation(msg *SetPageLocation, messageID uint64, timestamp uint64) { + b.pageEvent = &PageEvent{ + URL: msg.URL, + Referrer: msg.Referrer, + Loaded: true, + MessageID: messageID, + Timestamp: timestamp, + } +} + +func (b * pageEventBuilder) HandlePageLoadTiming(msg *PageLoadTiming) *PageEvent { + if !b.HasInstance() { + return nil + } + if msg.RequestStart <= 30000 { + b.pageEvent.RequestStart = msg.RequestStart + } + if msg.ResponseStart <= 30000 { + b.pageEvent.ResponseStart = msg.ResponseStart + } + if msg.ResponseEnd <= 30000 { + b.pageEvent.ResponseEnd = msg.ResponseEnd + } + if msg.DomContentLoadedEventStart <= 30000 { + b.pageEvent.DomContentLoadedEventStart = msg.DomContentLoadedEventStart + } + if msg.DomContentLoadedEventEnd <= 30000 { + b.pageEvent.DomContentLoadedEventEnd = msg.DomContentLoadedEventEnd + } + if msg.LoadEventStart <= 30000 { + b.pageEvent.LoadEventStart = msg.LoadEventStart + } + if msg.LoadEventEnd <= 30000 { + b.pageEvent.LoadEventEnd = msg.LoadEventEnd + } + if msg.FirstPaint <= 30000 { + b.pageEvent.FirstPaint = msg.FirstPaint + } + if msg.FirstContentfulPaint <= 30000 { + b.pageEvent.FirstContentfulPaint = msg.FirstContentfulPaint + } + return b.buildIfTimingsComplete() +} + +func (b * pageEventBuilder) HandlePageRenderTiming(msg *PageRenderTiming) *PageEvent { + if !b.HasInstance() { + return nil + } + b.pageEvent.SpeedIndex = msg.SpeedIndex + b.pageEvent.VisuallyComplete = msg.VisuallyComplete + b.pageEvent.TimeToInteractive = msg.TimeToInteractive + return b.buildIfTimingsComplete() +} + +func (b *pageEventBuilder) HasInstance() bool { + return b.pageEvent != nil +} + +func (b * pageEventBuilder) GetTimestamp() uint64 { + if b.pageEvent == nil { + return 0 + } + return b.pageEvent.Timestamp; +} + +func (b * pageEventBuilder) Build() *PageEvent { + pageEvent := b.pageEvent + b.pageEvent = nil + b.firstTimingHandled = false + return pageEvent +} \ No newline at end of file diff --git a/backend/services/ender/builder/performanceTrackAggrBuilder.go b/backend/services/ender/builder/performanceTrackAggrBuilder.go new file mode 100644 index 000000000..b24090ff9 --- /dev/null +++ b/backend/services/ender/builder/performanceTrackAggrBuilder.go @@ -0,0 +1,109 @@ +package builder + +import ( + "math" + + "openreplay/backend/pkg/messages/performance" + . "openreplay/backend/pkg/messages" +) + + +type performanceTrackAggrBuilder struct { + performanceTrackAggr *PerformanceTrackAggr + lastTimestamp uint64 + count float64 + sumFrameRate float64 + sumTickRate float64 + sumTotalJSHeapSize float64 + sumUsedJSHeapSize float64 +} + + +func (b *performanceTrackAggrBuilder) start(timestamp uint64) { + b.performanceTrackAggr = &PerformanceTrackAggr{ + TimestampStart: timestamp, + } + b.lastTimestamp = timestamp +} + +func (b *performanceTrackAggrBuilder) HandlePerformanceTrack(msg *PerformanceTrack, timestamp uint64) *PerformanceTrackAggr { + if msg.Frames == -1 || msg.Ticks == -1 || !b.HasInstance() { + performanceTrackAggr := b.Build() + b.start(timestamp) + return performanceTrackAggr + } + + dt := performance.TimeDiff(timestamp, b.lastTimestamp) + if dt == 0 { + return nil // TODO: handle error + } + + frameRate := performance.FrameRate(msg.Frames, dt) + tickRate := performance.TickRate(msg.Ticks, dt) + + fps := uint64(math.Round(frameRate)) + cpu := performance.CPURateFromTickRate(tickRate) + if fps < b.performanceTrackAggr.MinFPS || b.performanceTrackAggr.MinFPS == 0 { + b.performanceTrackAggr.MinFPS = fps + } + if fps > b.performanceTrackAggr.MaxFPS { + b.performanceTrackAggr.MaxFPS = fps + } + if cpu < b.performanceTrackAggr.MinCPU || b.performanceTrackAggr.MinCPU == 0 { + b.performanceTrackAggr.MinCPU = cpu + } + if cpu > b.performanceTrackAggr.MaxCPU { + b.performanceTrackAggr.MaxCPU = cpu + } + if msg.TotalJSHeapSize < b.performanceTrackAggr.MinTotalJSHeapSize || b.performanceTrackAggr.MinTotalJSHeapSize == 0 { + b.performanceTrackAggr.MinTotalJSHeapSize = msg.TotalJSHeapSize + } + if msg.TotalJSHeapSize > b.performanceTrackAggr.MaxTotalJSHeapSize { + b.performanceTrackAggr.MaxTotalJSHeapSize = msg.TotalJSHeapSize + } + if msg.UsedJSHeapSize < b.performanceTrackAggr.MinUsedJSHeapSize || b.performanceTrackAggr.MinUsedJSHeapSize == 0 { + b.performanceTrackAggr.MinUsedJSHeapSize = msg.UsedJSHeapSize + } + if msg.UsedJSHeapSize > b.performanceTrackAggr.MaxUsedJSHeapSize { + b.performanceTrackAggr.MaxUsedJSHeapSize = msg.UsedJSHeapSize + } + b.sumFrameRate += frameRate + b.sumTickRate += tickRate + b.sumTotalJSHeapSize += float64(msg.TotalJSHeapSize) + b.sumUsedJSHeapSize += float64(msg.UsedJSHeapSize) + b.count += 1 + b.lastTimestamp = timestamp + return nil +} + +func (b *performanceTrackAggrBuilder) HasInstance() bool { + return b.performanceTrackAggr != nil +} + +func (b *performanceTrackAggrBuilder) GetStartTimestamp() uint64 { + if b.performanceTrackAggr == nil { + return 0 + } + return b.performanceTrackAggr.TimestampStart; +} + +func (b *performanceTrackAggrBuilder) Build() *PerformanceTrackAggr { + var performanceTrackAggr *PerformanceTrackAggr + if b.HasInstance() && b.GetStartTimestamp() != b.lastTimestamp && b.count != 0 { + performanceTrackAggr = b.performanceTrackAggr + performanceTrackAggr.TimestampEnd = b.lastTimestamp + performanceTrackAggr.AvgFPS = uint64(math.Round(b.sumFrameRate / b.count)) + performanceTrackAggr.AvgCPU = 100 - uint64(math.Round(b.sumTickRate*100/b.count)) + performanceTrackAggr.AvgTotalJSHeapSize = uint64(math.Round(b.sumTotalJSHeapSize / b.count)) + performanceTrackAggr.AvgUsedJSHeapSize = uint64(math.Round(b.sumUsedJSHeapSize / b.count)) + } + b.performanceTrackAggr = nil + b.count = 0 + b.sumFrameRate = 0 + b.sumTickRate = 0 + b.sumTotalJSHeapSize = 0 + b.sumUsedJSHeapSize = 0 + b.lastTimestamp = 0 + return performanceTrackAggr +} + diff --git a/backend/services/ender/main.go b/backend/services/ender/main.go new file mode 100644 index 000000000..d1e83e545 --- /dev/null +++ b/backend/services/ender/main.go @@ -0,0 +1,72 @@ +package main + +import ( + "log" + "time" + + "os" + "os/signal" + "syscall" + + "openreplay/backend/pkg/intervals" + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/queue/types" + "openreplay/backend/services/ender/builder" +) + + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + + GROUP_EVENTS := env.String("GROUP_ENDER") + TOPIC_TRIGGER := env.String("TOPIC_TRIGGER") + + builderMap := builder.NewBuilderMap() + var lastTs int64 = 0 + + producer := queue.NewProducer() + consumer := queue.NewMessageConsumer( + GROUP_EVENTS, + []string{ + env.String("TOPIC_RAW"), + }, + func(sessionID uint64, msg messages.Message, meta *types.Meta) { + lastTs = meta.Timestamp + builderMap.HandleMessage(sessionID, msg, msg.Meta().Index) + // builderMap.IterateSessionReadyMessages(sessionID, lastTs, func(readyMsg messages.Message) { + // producer.Produce(TOPIC_TRIGGER, sessionID, messages.Encode(readyMsg)) + // }) + }, + ) + consumer.DisableAutoCommit() + + tick := time.Tick(intervals.EVENTS_COMMIT_INTERVAL * time.Millisecond) + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + producer.Close(2000) + consumer.CommitBack(intervals.EVENTS_BACK_COMMIT_GAP) + consumer.Close() + os.Exit(0) + case <- tick: + builderMap.IterateReadyMessages(time.Now().UnixNano()/1e6, func(sessionID uint64, readyMsg messages.Message) { + producer.Produce(TOPIC_TRIGGER, sessionID, messages.Encode(readyMsg)) + }) + // TODO: why exactly do we need Flush here and not in any other place? + producer.Flush(2000) + consumer.CommitBack(intervals.EVENTS_BACK_COMMIT_GAP) + default: + if err := consumer.ConsumeNext(); err != nil { + log.Fatalf("Error on consuming: %v", err) + } + } + } +} + diff --git a/backend/services/http/README.md b/backend/services/http/README.md new file mode 100644 index 000000000..f55051a82 --- /dev/null +++ b/backend/services/http/README.md @@ -0,0 +1,72 @@ +# HTTP Endpoints + +## Start Mobile Session +`POST` /v1/ios/start +### Request +`application/json` + +``` +* - required +{ + projectID* number // Encoded ProjectID + trackerVersion* string // Tracker version string + revID string // Set by user + userUUID string // User ID, should be derived from local storage connected to user + userOSVersion string + userDevice string + userDeviceType number // + performance // +} +``` + +### Responce + +``` +200 application/json +{ + imagesHashList // list of most friquently used image hash strings + token // Authorisation token to use in other requests (Bearer) + userUUID // Should be stored in local storage +} +``` + + +## Push message batch +`POST` /v1/ios/append +### Request +`application/octet-stream` +``` + +``` +### Responce +200 OK + +OR + +401 Unauthorised - token timed out. Start new session + + +## Push late message batch (after app reload - crashes etc.) +`POST` /v1/ios/late +### Request +`application/octet-stream` +``` + +``` +### Responce +200 OK + + + +## Push images +`POST` /v1/ios/images + +### Request +`multipart/form-data` values: +`projectID` [required] // Encoded ProjectID + +Binary files with the hash-filename in the `filename` header each. + + +### Responce +200 OK diff --git a/backend/services/http/assets.go b/backend/services/http/assets.go new file mode 100644 index 000000000..637aa5a5b --- /dev/null +++ b/backend/services/http/assets.go @@ -0,0 +1,20 @@ +package main + +import ( + "openreplay/backend/pkg/url/assets" + "openreplay/backend/pkg/messages" +) + +func sendAssetForCache(sessionID uint64, baseURL string, relativeURL string) { + if fullURL, cachable := assets.GetFullCachableURL(baseURL, relativeURL); cachable { + producer.Produce(topicTrigger, sessionID, messages.Encode(&messages.AssetCache{ + URL: fullURL, + })) + } +} + +func sendAssetsForCacheFromCSS(sessionID uint64, baseURL string, css string) { + for _, u := range assets.ExtractURLsFromCSS(css) { // TODO: in one shot with rewriting + sendAssetForCache(sessionID, baseURL, u) + } +} \ No newline at end of file diff --git a/backend/services/http/geoip/geoip.go b/backend/services/http/geoip/geoip.go new file mode 100644 index 000000000..131996d7c --- /dev/null +++ b/backend/services/http/geoip/geoip.go @@ -0,0 +1,41 @@ +package geoip + +import ( + "log" + "net" + + maxminddb "github.com/oschwald/maxminddb-golang" +) + +type geoIPRecord struct { + Country struct { + ISOCode string `maxminddb:"iso_code"` + } `maxminddb:"country"` +} + +type GeoIP struct { + r *maxminddb.Reader +} + +func NewGeoIP(file string) *GeoIP { + r, err := maxminddb.Open(file) + if err != nil { + log.Fatalln(err) + } + return &GeoIP{r} +} + +func (geoIP *GeoIP) ExtractISOCode(ip net.IP) string { + if ip == nil { + return "UN" + } + var code string + var record geoIPRecord + if geoIP.r.Lookup(ip, &record) == nil { + code = record.Country.ISOCode + } + if code == "" { + code = "UN" + } + return code +} diff --git a/backend/services/http/geoip/http.go b/backend/services/http/geoip/http.go new file mode 100644 index 000000000..49f919b92 --- /dev/null +++ b/backend/services/http/geoip/http.go @@ -0,0 +1,13 @@ +package geoip + +import ( + "net" + "net/http" + + "github.com/tomasen/realip" +) + +func (geoIP *GeoIP) ExtractISOCodeFromHTTPRequest(r *http.Request) string { + ip := net.ParseIP(realip.FromRequest(r)) + return geoIP.ExtractISOCode(ip) +} diff --git a/backend/services/http/handlers.go b/backend/services/http/handlers.go new file mode 100644 index 000000000..252eddc5a --- /dev/null +++ b/backend/services/http/handlers.go @@ -0,0 +1,295 @@ +package main + +import ( + "encoding/json" + "errors" + "time" + "log" + "io" + "io/ioutil" + "net/http" + "math/rand" + "strconv" + + gzip "github.com/klauspost/pgzip" + + . "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/pkg/token" +) + +const JSON_SIZE_LIMIT int64 = 1e3 // 1Kb +const BATCH_SIZE_LIMIT int64 = 1e6 // 1Mb + +func startSessionHandlerWeb(w http.ResponseWriter, r *http.Request) { + type request struct { + Token string `json:"token"` + UserUUID *string `json:"userUUID"` + RevID string `json:"revID"` + Timestamp uint64 `json:"timestamp"` + TrackerVersion string `json:"trackerVersion"` + IsSnippet bool `json:"isSnippet"` + DeviceMemory uint64 `json:"deviceMemory"` + JsHeapSizeLimit uint64 `json:"jsHeapSizeLimit"` + ProjectKey *string `json:"projectKey"` + } + type response struct { + Timestamp int64 `json:"timestamp"` + Delay int64 `json:"delay"` + Token string `json:"token"` + UserUUID string `json:"userUUID"` + SessionID string `json:"sessionID"` + } + + startTime := time.Now() + req := &request{} + body := http.MaxBytesReader(w, r.Body, JSON_SIZE_LIMIT) // what if Body == nil?? // use r.ContentLength to return specific error? + //defer body.Close() + if err := json.NewDecoder(body).Decode(req); err != nil { + responseWithError(w, http.StatusBadRequest, err) + return + } + + if req.ProjectKey == nil { + responseWithError(w, http.StatusForbidden, errors.New("ProjectKey value required")) + return + } + + p, err := pgconn.GetProjectByKey(*req.ProjectKey) + if p == nil { + if err == nil { + responseWithError(w, http.StatusNotFound, errors.New("Project doesn't exist or is not active")) + } else { + responseWithError(w, http.StatusInternalServerError, err) // TODO: send error here only on staging + } + return + } + + dice := byte(rand.Intn(100)) // [0, 100) + if dice >= p.SampleRate { + responseWithError(w, http.StatusForbidden, errors.New("cancel")) + return + } + + userUUID := getUUID(req.UserUUID) + tokenData, err := tokenizer.Parse(req.Token) + if err != nil { // Starting the new one + ua := uaParser.ParseFromHTTPRequest(r) + if ua == nil { + responseWithError(w, http.StatusForbidden, errors.New("browser not recognized")) + return + } + sessionID, err := flaker.Compose(uint64(startTime.UnixNano() / 1e6)) + if err != nil { + responseWithError(w, http.StatusInternalServerError, err) + return + } + // TODO: if EXPIRED => send message for two sessions association + expTime := startTime.Add(time.Duration(p.MaxSessionDuration) * time.Millisecond) + tokenData = &token.TokenData{sessionID, expTime.UnixNano() / 1e6} + + country := geoIP.ExtractISOCodeFromHTTPRequest(r) + producer.Produce(topicRaw, tokenData.ID, Encode(&SessionStart{ + Timestamp: req.Timestamp, + ProjectID: uint64(p.ProjectID), + TrackerVersion: req.TrackerVersion, + RevID: req.RevID, + UserUUID: userUUID, + UserAgent: r.Header.Get("User-Agent"), + UserOS: ua.OS, + UserOSVersion: ua.OSVersion, + UserBrowser: ua.Browser, + UserBrowserVersion: ua.BrowserVersion, + UserDevice: ua.Device, + UserDeviceType: ua.DeviceType, + UserCountry: country, + UserDeviceMemorySize: req.DeviceMemory, + UserDeviceHeapSize: req.JsHeapSizeLimit, + })) + } + + //delayDuration := time.Now().Sub(startTime) + responseWithJSON(w, &response{ + //Timestamp: startTime.UnixNano() / 1e6, + //Delay: delayDuration.Nanoseconds() / 1e6, + Token: tokenizer.Compose(*tokenData), + UserUUID: userUUID, + SessionID: strconv.FormatUint(tokenData.ID, 10), + }) +} + + + +func pushMessages(w http.ResponseWriter, r *http.Request, sessionID uint64) { + body := http.MaxBytesReader(w, r.Body, BATCH_SIZE_LIMIT) + //defer body.Close() + var reader io.ReadCloser + switch r.Header.Get("Content-Encoding") { + case "gzip": + reader, err := gzip.NewReader(body) + if err != nil { + responseWithError(w, http.StatusInternalServerError, err) // TODO: stage-dependent responce + return + } + defer reader.Close() + default: + reader = body + } + buf, err := ioutil.ReadAll(reader) + if err != nil { + responseWithError(w, http.StatusInternalServerError, err) // TODO: send error here only on staging + return + } + producer.Produce(topicRaw, sessionID, buf) // What if not able to send? + w.WriteHeader(http.StatusOK) +} + +func pushMessagesHandler(w http.ResponseWriter, r *http.Request) { + sessionData, err := tokenizer.ParseFromHTTPRequest(r) + if err != nil { + responseWithError(w, http.StatusUnauthorized, err) + return + } + pushMessages(w, r, sessionData.ID) +} + +func pushMessagesSeparatelyHandler(w http.ResponseWriter, r *http.Request) { + sessionData, err := tokenizer.ParseFromHTTPRequest(r) + if err != nil { + responseWithError(w, http.StatusUnauthorized, err) + return + } + body := http.MaxBytesReader(w, r.Body, BATCH_SIZE_LIMIT) + //defer body.Close() + buf, err := ioutil.ReadAll(body) + if err != nil { + responseWithError(w, http.StatusInternalServerError, err) // TODO: send error here only on staging + return + } + //log.Printf("Sending batch...") + //startTime := time.Now() + +// analyticsMessages := make([]Message, 0, 200) + + rewritenBuf, err := RewriteBatch(buf, func(msg Message) Message { + switch m := msg.(type) { + case *SetNodeAttributeURLBased: + if m.Name == "src" || m.Name == "href" { + sendAssetForCache(sessionData.ID, m.BaseURL, m.Value) + msg = &SetNodeAttribute{ + ID: m.ID, + Name: m.Name, + Value: rewriter.RewriteURL(sessionData.ID, m.BaseURL, m.Value), + } + } else if m.Name == "style" { + sendAssetsForCacheFromCSS(sessionData.ID, m.BaseURL, m.Value) + msg = &SetNodeAttribute{ + ID: m.ID, + Name: m.Name, + Value: rewriter.RewriteCSS(sessionData.ID, m.BaseURL, m.Value), + } + } + case *SetCSSDataURLBased: + sendAssetsForCacheFromCSS(sessionData.ID, m.BaseURL, m.Data) + msg = &SetCSSData{ + ID: m.ID, + Data: rewriter.RewriteCSS(sessionData.ID, m.BaseURL, m.Data), + } + case *CSSInsertRuleURLBased: + sendAssetsForCacheFromCSS(sessionData.ID, m.BaseURL, m.Rule) + msg = &CSSInsertRule{ + ID: m.ID, + Index: m.Index, + Rule: rewriter.RewriteCSS(sessionData.ID, m.BaseURL, m.Rule), + } + } + + // switch msg.(type) { + // case *BatchMeta, // TODO: watchout! Meta().Index'es are changed here (though it is still unique for the topic-session pair) + // *SetPageLocation, + // *PageLoadTiming, + // *PageRenderTiming, + // *PerformanceTrack, + // *SetInputTarget, + // *SetInputValue, + // *MouseClick, + // *RawErrorEvent, + // *JSException, + // *ResourceTiming, + // *RawCustomEvent, + // *CustomIssue, + // *Fetch, + // *StateAction, + // *GraphQL, + // *CreateElementNode, + // *CreateTextNode, + // *RemoveNode, + // *CreateDocument, + // *RemoveNodeAttribute, + // *MoveNode, + // *SetCSSData, + // *CSSInsertRule, + // *CSSDeleteRule: + // analyticsMessages = append(analyticsMessages, msg) + //} + + + + return msg + }) + if err != nil { + responseWithError(w, http.StatusForbidden, err) + return + } + producer.Produce(topicRaw, sessionData.ID, rewritenBuf) + //producer.Produce(topicAnalytics, sessionData.ID, WriteBatch(analyticsMessages)) + //duration := time.Now().Sub(startTime) + //log.Printf("Sended batch within %v nsec; %v nsek/byte", duration.Nanoseconds(), duration.Nanoseconds()/int64(len(buf))) + w.WriteHeader(http.StatusOK) +} + +func notStartedHandler(w http.ResponseWriter, r *http.Request) { + type request struct { + ProjectKey *string `json:"projectKey"` + TrackerVersion string `json:"trackerVersion"` + DoNotTrack bool `json:"DoNotTrack"` + // RevID string `json:"revID"` + } + req := &request{} + body := http.MaxBytesReader(w, r.Body, JSON_SIZE_LIMIT) + defer body.Close() + if err := json.NewDecoder(body).Decode(req); err != nil { + responseWithError(w, http.StatusBadRequest, err) + return + } + if req.ProjectKey == nil { + responseWithError(w, http.StatusForbidden, errors.New("ProjectKey value required")) + return + } + ua := uaParser.ParseFromHTTPRequest(r) // TODO?: insert anyway + if ua == nil { + responseWithError(w, http.StatusForbidden, errors.New("browser not recognized")) + return + } + country := geoIP.ExtractISOCodeFromHTTPRequest(r) + err := pgconn.InsertUnstartedSession(postgres.UnstartedSession{ + ProjectKey: *req.ProjectKey, + TrackerVersion: req.TrackerVersion, + DoNotTrack: req.DoNotTrack, + Platform: "web", + UserAgent: r.Header.Get("User-Agent"), + UserOS: ua.OS, + UserOSVersion: ua.OSVersion, + UserBrowser: ua.Browser, + UserBrowserVersion: ua.BrowserVersion, + UserDevice: ua.Device, + UserDeviceType: ua.DeviceType, + UserCountry: country, + }) + if err != nil { + log.Printf("Unable to insert Unstarted Session: %v\n", err); + } + w.WriteHeader(http.StatusOK) +} + + diff --git a/backend/services/http/handlers_ios.go b/backend/services/http/handlers_ios.go new file mode 100644 index 000000000..2c874a312 --- /dev/null +++ b/backend/services/http/handlers_ios.go @@ -0,0 +1,145 @@ +package main + +// const FILES_SIZE_LIMIT int64 = 1e8 // 100Mb + +// func startSessionHandlerIOS(w http.ResponseWriter, r *http.Request) { +// type request struct { +// // SessionID *string +// EncodedProjectID *uint64 `json:"projectID"` +// TrackerVersion string `json:"trackerVersion"` +// RevID string `json:"revID"` +// UserUUID *string `json:"userUUID"` +// //UserOS string `json"userOS"` //hardcoded 'MacOS' +// UserOSVersion string `json:"userOSVersion"` +// UserDevice string `json:"userDevice"` +// Timestamp uint64 `json:"timestamp"` +// // UserDeviceType uint 0:phone 1:pad 2:tv 3:carPlay 5:mac +// // “performances”:{ +// // “activeProcessorCount”:8, +// // “isLowPowerModeEnabled”:0, +// // “orientation”:0, +// // “systemUptime”:585430, +// // “batteryState”:0, +// // “thermalState”:0, +// // “batteryLevel”:0, +// // “processorCount”:8, +// // “physicalMemory”:17179869184 +// // }, +// } +// type response struct { +// Token string `json:"token"` +// ImagesHashList []string `json:"imagesHashList"` +// UserUUID string `json:"userUUID"` +// SESSION_ID uint64 `json:"SESSION_ID"` ///TEMP +// } +// startTime := time.Now() +// req := &request{} +// body := http.MaxBytesReader(w, r.Body, JSON_SIZE_LIMIT) +// //defer body.Close() +// if err := json.NewDecoder(body).Decode(req); err != nil { +// responseWithError(w, http.StatusBadRequest, err) +// return +// } + +// if req.EncodedProjectID == nil { +// responseWithError(w, http.StatusForbidden, errors.New("ProjectID value required")) +// return +// } +// projectID := decodeProjectID(*(req.EncodedProjectID)) +// if projectID == 0 { +// responseWithError(w, http.StatusUnprocessableEntity, errors.New("ProjectID value is invalid")) +// return +// } +// p, err := pgconn.GetProject(uint32(projectID)) +// if p == nil { +// if err == nil { +// responseWithError(w, http.StatusNotFound, errors.New("Project doesn't exist or is not active")) +// } else { +// responseWithError(w, http.StatusInternalServerError, err) // TODO: send error here only on staging +// } +// return +// } +// sessionID, err := flaker.Compose(req.Timestamp) +// if err != nil { +// responseWithError(w, http.StatusInternalServerError, err) +// return +// } +// userUUID := getUUID(req.UserUUID) +// country := geoIP.ExtractISOCodeFromHTTPRequest(r) +// expirationTime := startTime.Add(time.Duration(p.MaxSessionDuration) * time.Millisecond) + +// imagesHashList, err := s3.GetFrequentlyUsedKeys(*(req.EncodedProjectID)) // TODO: reuse index: ~ frequency * size +// if err != nil { +// responseWithError(w, http.StatusInternalServerError, err) +// return +// } + +// responseWithJSON(w, &response{ +// Token: tokenizer.Compose(sessionID, uint64(expirationTime.UnixNano()/1e6)), +// ImagesHashList: imagesHashList, +// UserUUID: userUUID, +// //TEMP: +// SESSION_ID: sessionID, +// }) +// producer.Produce(topicRaw, sessionID, messages.Encode(&messages.IOSSessionStart{ +// Timestamp: req.Timestamp, +// ProjectID: projectID, +// TrackerVersion: req.TrackerVersion, +// RevID: req.RevID, +// UserUUID: userUUID, +// UserOS: "MacOS", +// UserOSVersion: req.UserOSVersion, +// UserDevice: MapIOSDevice(req.UserDevice), +// UserDeviceType: GetIOSDeviceType(req.UserDevice), // string `json:"userDeviceType"` // From UserDevice; ENUM ? +// UserCountry: country, +// })) +// } + + +// func pushLateMessagesHandler(w http.ResponseWriter, r *http.Request) { +// sessionData, err := tokenizer.ParseFromHTTPRequest(r) +// if err != nil && err != token.EXPIRED { +// responseWithError(w, http.StatusUnauthorized, err) +// return +// } +// // Check timestamps here? +// pushMessages(w, r, sessionData.ID) +// } + + +// func iosImagesUploadHandler(w http.ResponseWriter, r *http.Request) { +// r.Body = http.MaxBytesReader(w, r.Body, FILES_SIZE_LIMIT) +// // defer r.Body.Close() +// err := r.ParseMultipartForm(1e5) // 100Kb +// if err == http.ErrNotMultipart || err == http.ErrMissingBoundary { +// responseWithError(w, http.StatusUnsupportedMediaType, err) +// // } else if err == multipart.ErrMessageTooLarge // if non-files part exceeds 10 MB +// } else if err != nil { +// responseWithError(w, http.StatusInternalServerError, err) // TODO: send error here only on staging +// } + +// if len(r.MultipartForm.Value["projectID"]) == 0 { +// responseWithError(w, http.StatusBadRequest, errors.New("projectID parameter required")) // status for missing/wrong parameter? +// return +// } +// // encodedProjectID, err := strconv.ParseUint(r.MultipartForm.Value["projectID"][0], 10, 64) +// // projectID := decodeProjectID(encodedProjectID) +// // if projectID == 0 || err != nil { +// // responseWithError(w, http.StatusUnprocessableEntity, errors.New("projectID value is incorrect")) +// // return +// // } +// prefix := r.MultipartForm.Value["projectID"][0] + "/" //strconv.FormatUint(uint64(projectID), 10) + "/" + +// for _, fileHeaderList := range r.MultipartForm.File { +// for _, fileHeader := range fileHeaderList { +// file, err := fileHeader.Open() +// if err != nil { +// continue // TODO: send server error or accumulate successful files +// } +// key := prefix + fileHeader.Filename // TODO: Malicious image put: use jwt? +// go s3.Upload(file, key, "image/png", false) +// } +// } + +// w.WriteHeader(http.StatusOK) +// } diff --git a/backend/services/http/ios_device.go b/backend/services/http/ios_device.go new file mode 100644 index 000000000..2c3474157 --- /dev/null +++ b/backend/services/http/ios_device.go @@ -0,0 +1,79 @@ +package main + +import ( + "strings" +) + +func MapIOSDevice(identifier string) string { + switch identifier { + case "iPod5,1": return "iPod touch (5th generation)" + case "iPod7,1": return "iPod touch (6th generation)" + case "iPod9,1": return "iPod touch (7th generation)" + case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4" + case "iPhone4,1": return "iPhone 4s" + case "iPhone5,1", "iPhone5,2": return "iPhone 5" + case "iPhone5,3", "iPhone5,4": return "iPhone 5c" + case "iPhone6,1", "iPhone6,2": return "iPhone 5s" + case "iPhone7,2": return "iPhone 6" + case "iPhone7,1": return "iPhone 6 Plus" + case "iPhone8,1": return "iPhone 6s" + case "iPhone8,2": return "iPhone 6s Plus" + case "iPhone8,4": return "iPhone SE" + case "iPhone9,1", "iPhone9,3": return "iPhone 7" + case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus" + case "iPhone10,1", "iPhone10,4": return "iPhone 8" + case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus" + case "iPhone10,3", "iPhone10,6": return "iPhone X" + case "iPhone11,2": return "iPhone XS" + case "iPhone11,4", "iPhone11,6": return "iPhone XS Max" + case "iPhone11,8": return "iPhone XR" + case "iPhone12,1": return "iPhone 11" + case "iPhone12,3": return "iPhone 11 Pro" + case "iPhone12,5": return "iPhone 11 Pro Max" + case "iPhone12,8": return "iPhone SE (2nd generation)" + case "iPhone13,1": return "iPhone 12 mini" + case "iPhone13,2": return "iPhone 12" + case "iPhone13,3": return "iPhone 12 Pro" + case "iPhone13,4": return "iPhone 12 Pro Max" + case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2" + case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)" + case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)" + case "iPad6,11", "iPad6,12": return "iPad (5th generation)" + case "iPad7,5", "iPad7,6": return "iPad (6th generation)" + case "iPad7,11", "iPad7,12": return "iPad (7th generation)" + case "iPad11,6", "iPad11,7": return "iPad (8th generation)" + case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air" + case "iPad5,3", "iPad5,4": return "iPad Air 2" + case "iPad11,3", "iPad11,4": return "iPad Air (3rd generation)" + case "iPad13,1", "iPad13,2": return "iPad Air (4th generation)" + case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad mini" + case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad mini 2" + case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad mini 3" + case "iPad5,1", "iPad5,2": return "iPad mini 4" + case "iPad11,1", "iPad11,2": return "iPad mini (5th generation)" + case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)" + case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)" + case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch) (1st generation)" + case "iPad8,9", "iPad8,10": return "iPad Pro (11-inch) (2nd generation)" + case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch) (1st generation)" + case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)" + case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)" + case "iPad8,11", "iPad8,12": return "iPad Pro (12.9-inch) (4th generation)" + case "AppleTV5,3": return "Apple TV" + case "AppleTV6,2": return "Apple TV 4K" + case "AudioAccessory1,1": return "HomePod" + case "AudioAccessory5,1": return "HomePod mini" + case "i386", "x86_64": return "Simulator" + default: return identifier + } +} + +func GetIOSDeviceType(identifier string) string { + if strings.Contains(identifier, "iPhone") { + return "mobile" //"phone" + } + if strings.Contains(identifier, "iPad") { + return "tablet" + } + return "other" +} \ No newline at end of file diff --git a/backend/services/http/main.go b/backend/services/http/main.go new file mode 100644 index 000000000..b3e3b6d9d --- /dev/null +++ b/backend/services/http/main.go @@ -0,0 +1,137 @@ +package main + +import ( + "context" + "log" + "net/http" + "os" + "os/signal" + "syscall" + + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/flakeid" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/queue/types" + "openreplay/backend/pkg/storage" + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/pkg/db/cache" + "openreplay/backend/pkg/url/assets" + "openreplay/backend/pkg/token" + "openreplay/backend/services/http/geoip" + "openreplay/backend/services/http/uaparser" + +) + +var rewriter *assets.Rewriter +var producer types.Producer +var pgconn *cache.PGCache +var flaker *flakeid.Flaker +var uaParser *uaparser.UAParser +var geoIP *geoip.GeoIP +var tokenizer *token.Tokenizer +var s3 *storage.S3 +var topicRaw string +var topicTrigger string +var topicAnalytics string +// var kafkaTopicEvents string + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + + producer = queue.NewProducer() + defer producer.Close(15000) + topicRaw = env.String("TOPIC_RAW") + topicTrigger = env.String("TOPIC_TRIGGER") + topicAnalytics = env.String("TOPIC_ANALYTICS") + rewriter = assets.NewRewriter(env.String("ASSETS_ORIGIN")) + pgconn = cache.NewPGCache(postgres.NewConn(env.String("POSTGRES_STRING")), 1000 * 60 * 20) + defer pgconn.Close() + //s3 = storage.NewS3(env.String("S3_BUCKET_IMAGES_IOS"), env.String("AWS_REGION")) + tokenizer = token.NewTokenizer(env.String("TOKEN_SECRET")) + uaParser = uaparser.NewUAParser(env.String("UAPARSER_FILE")) + geoIP = geoip.NewGeoIP(env.String("MAXMINDDB_FILE")) + flaker = flakeid.NewFlaker(env.WorkerID()) + HTTP_PORT := env.String("HTTP_PORT") + + server := &http.Server{ + Addr: ":" + HTTP_PORT, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + // TODO: agree with specification + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization") + if r.Method == http.MethodOptions { + w.WriteHeader(http.StatusOK) + return + } + switch r.URL.Path { + case "/": + w.WriteHeader(http.StatusOK) + case "/v1/web/not-started": + switch r.Method { + case "POST": + notStartedHandler(w, r) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + } + case "/v1/web/start": + switch r.Method { + case "POST": + startSessionHandlerWeb(w, r) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + } + case "/v1/web/i": + switch r.Method { + case "POST": + pushMessagesSeparatelyHandler(w, r) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + } + // case "/v1/ios/start": + // switch r.Method { + // case "POST": + // startSessionHandlerIOS(w, r) + // default: + // w.WriteHeader(http.StatusMethodNotAllowed) + // } + // case "/v1/ios/append": + // switch r.Method { + // case "POST": + // pushMessagesHandler(w, r) + // default: + // w.WriteHeader(http.StatusMethodNotAllowed) + // } + // case "/v1/ios/late": + // switch r.Method { + // case "POST": + // pushLateMessagesHandler(w, r) + // default: + // w.WriteHeader(http.StatusMethodNotAllowed) + // } + // case "/v1/ios/images": + // switch r.Method { + // case "POST": + // iosImagesUploadHandler(w, r) + // default: + // w.WriteHeader(http.StatusMethodNotAllowed) + // } + default: + w.WriteHeader(http.StatusNotFound) + } + }), + } + go func() { + if err := server.ListenAndServe(); err != nil { + log.Fatalf("Server error: %v\n", err) + } + }() + log.Printf("Server successfully started on port %v\n", HTTP_PORT) + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + <-sigchan + log.Printf("Shutting down the server\n") + server.Shutdown(context.Background()) +} diff --git a/backend/services/http/project_id.go b/backend/services/http/project_id.go new file mode 100644 index 000000000..059576fe8 --- /dev/null +++ b/backend/services/http/project_id.go @@ -0,0 +1,12 @@ +package main + +func decodeProjectID(projectID uint64) uint64 { + if projectID < 0x10000000000000 || projectID >= 0x20000000000000 { + return 0 + } + projectID = (projectID - 0x10000000000000) * 4212451012670231 & 0xfffffffffffff + if projectID > 0xffffffff { + return 0 + } + return projectID +} diff --git a/backend/services/http/response.go b/backend/services/http/response.go new file mode 100644 index 000000000..ffd22875e --- /dev/null +++ b/backend/services/http/response.go @@ -0,0 +1,23 @@ +package main + +import ( + "encoding/json" + "log" + "net/http" +) + +func responseWithJSON(w http.ResponseWriter, res interface{}) { + body, err := json.Marshal(res) + if err != nil { + log.Println(err) + } + w.Write(body) +} + +func responseWithError(w http.ResponseWriter, code int, err error) { + type response struct { + Error string `json:"error"` + } + w.WriteHeader(code) + responseWithJSON(w, &response{err.Error()}) +} diff --git a/backend/services/http/uaparser/http.go b/backend/services/http/uaparser/http.go new file mode 100644 index 000000000..1ed6b0a24 --- /dev/null +++ b/backend/services/http/uaparser/http.go @@ -0,0 +1,8 @@ +package uaparser + +import "net/http" + +func (parser *UAParser) ParseFromHTTPRequest(r *http.Request) *UA { + str := r.Header.Get("User-Agent") + return parser.Parse(str) +} diff --git a/backend/services/http/uaparser/uaparser.go b/backend/services/http/uaparser/uaparser.go new file mode 100644 index 000000000..e2bc78d9a --- /dev/null +++ b/backend/services/http/uaparser/uaparser.go @@ -0,0 +1,77 @@ +package uaparser + +import ( + "log" + "strings" + + "github.com/ua-parser/uap-go/uaparser" +) + +type UAParser struct { + p *uaparser.Parser +} + +func NewUAParser(regexFile string) *UAParser { + p, err := uaparser.New(regexFile) + if err != nil { + log.Fatalln(err) + } + return &UAParser{p} +} + +type UA struct { + OS string + OSVersion string + Browser string + BrowserVersion string + Device string + DeviceType string +} + +func (parser *UAParser) Parse(str string) *UA { + if str == "" { + return nil + } + data := parser.p.Parse(str) + if data == nil { + return nil + } + ua := &UA{ + OS: data.Os.Family, + Browser: strings.Split(data.UserAgent.Family, "/")[0], + Device: data.Device.Family, + } + if ua.OS == "" || ua.Browser == "" || ua.Device == "Spider" { + return nil + } + if ua.Device == "Other" || ua.Device == "Mac" { + ua.Device = "" + } + if data.Os.Major != "" { + ua.OSVersion += data.Os.Major + if data.Os.Minor != "" { + ua.OSVersion += "." + data.Os.Minor + if data.Os.Patch != "" { + ua.OSVersion += "." + data.Os.Patch + } + } + } + if data.UserAgent.Major != "" { + ua.BrowserVersion += data.UserAgent.Major + if data.UserAgent.Minor != "" { + ua.BrowserVersion += "." + data.UserAgent.Minor + if data.UserAgent.Patch != "" { + ua.BrowserVersion += "." + data.UserAgent.Patch + } + } + } + switch ua.OS { + case "Chrome OS", "Fedora", "FreeBSD", "Linux", "Mac OS X", "NetBSD", "Ubuntu", "Windows": + ua.DeviceType = "desktop" + case "Android", "BlackBerry OS", "BlackBerry Tablet OS", "iOS", "Windows Phone": + ua.DeviceType = "mobile" + default: + ua.DeviceType = "other" + } + return ua +} diff --git a/backend/services/http/uuid.go b/backend/services/http/uuid.go new file mode 100644 index 000000000..13f57bff0 --- /dev/null +++ b/backend/services/http/uuid.go @@ -0,0 +1,15 @@ +package main + +import ( + "github.com/google/uuid" +) + +func getUUID(u *string) string { + if u != nil { + _, err := uuid.Parse(*u) + if err == nil { + return *u + } + } + return uuid.New().String() +} \ No newline at end of file diff --git a/backend/services/integrations/clientManager/manager.go b/backend/services/integrations/clientManager/manager.go new file mode 100644 index 000000000..39cd8dd90 --- /dev/null +++ b/backend/services/integrations/clientManager/manager.go @@ -0,0 +1,51 @@ +package clientManager + +import ( + "strconv" + + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/services/integrations/integration" +) + + +type manager struct { + clientMap integration.ClientMap + Events chan *integration.SessionErrorEvent + Errors chan error + RequestDataUpdates chan postgres.Integration // not pointer because it could change in other thread +} + + +func NewManager() *manager { + return &manager { + clientMap: make(integration.ClientMap), + RequestDataUpdates: make(chan postgres.Integration, 100), + Events: make(chan *integration.SessionErrorEvent, 100), + Errors: make(chan error, 100), + } + +} + +func (m* manager) Update(i *postgres.Integration) error { + key := strconv.Itoa(int(i.ProjectID)) + i.Provider + if i.Options == nil { + delete(m.clientMap, key) + return nil + } + c, exists := m.clientMap[ key ] + if !exists { + c, err := integration.NewClient(i, m.RequestDataUpdates, m.Events, m.Errors) + if err != nil { + return err + } + m.clientMap[ key ] = c + return nil + } + return c.Update(i) +} + +func (m *manager) RequestAll() { + for _, c := range m.clientMap { + go c.Request() + } +} diff --git a/backend/services/integrations/integration/bugsnag.go b/backend/services/integrations/integration/bugsnag.go new file mode 100644 index 000000000..7c31db3cb --- /dev/null +++ b/backend/services/integrations/integration/bugsnag.go @@ -0,0 +1,123 @@ +package integration + +import ( + "fmt" + "net/http" + "encoding/json" + "net/url" + "time" + "io" + "io/ioutil" + + "openreplay/backend/pkg/utime" + "openreplay/backend/pkg/messages" +) + +/* + - Bugsnag messages usually recived later then others +*/ + +type bugsnag struct { + BugsnagProjectId string // `json:"bugsnag_project_id"` + AuthorizationToken string // `json:"auth_token"` +} + + +type bugsnagEvent struct { + MetaData struct { + SpecialInfo struct { + AsayerSessionId uint64 `json:"asayerSessionId,string"` + OpenReplaySessionToken string `json:"openReplaySessionToken"` + } `json:"special_info"` + } `json:"metaData"` + ReceivedAt string `json:"received_at"` // can use time.Time as it implements UnmarshalJSON from RFC3339 format + Exceptions [1]struct { + Message string + } +} + +func (b *bugsnag) Request(c *client) error { + sinceTs := c.getLastMessageTimestamp() + 1000 // From next second + sinceFormatted := time.Unix(0, int64(sinceTs*1e6)).Format(time.RFC3339) + requestURL := fmt.Sprintf("https://api.bugsnag.com/projects/%v/events", b.BugsnagProjectId) + req, err := http.NewRequest("GET", requestURL, nil) + if err != nil { + return err + } + q := req.URL.Query() + // q.Add("per_page", "100") // Up to a maximum of 30. Default: 30 + // q.Add("sort", "timestamp") // Default: timestamp (timestamp == ReceivedAt ??) + q.Add("direction", "asc") // Default: desc + q.Add("full_reports", "true") // Default: false + q.Add("filters[event.since][][type]", "eq") + q.Add("filters[event.since][][value]", sinceFormatted) // seems like inclusively + req.URL.RawQuery = q.Encode() + + authToken := "token " + b.AuthorizationToken + req.Header.Add("Authorization", authToken) + req.Header.Add("X-Version", "2") + + for { + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + // Status code + // 401 (unauthorised) + if resp.StatusCode >= 400 { + io.Copy(ioutil.Discard, resp.Body) // Read the body to free socket + return fmt.Errorf("Bugsnag: server respond with the code %v | data: %v ", resp.StatusCode, *b) + } + + var jsonEventList []json.RawMessage + err = json.NewDecoder(resp.Body).Decode(&jsonEventList) + if err != nil { + return err + } + for _, jsonEvent := range jsonEventList { + var e bugsnagEvent + err = json.Unmarshal(jsonEvent, &e) + if err != nil { + c.errChan <- err + continue + } + sessionID := e.MetaData.SpecialInfo.AsayerSessionId + token := e.MetaData.SpecialInfo.OpenReplaySessionToken + if sessionID == 0 && token == "" { + // c.errChan <- "No AsayerSessionId found. | Message: %v", e + continue + } + parsedTime, err := time.Parse(time.RFC3339, e.ReceivedAt) + if err != nil { + c.errChan <- err + continue + } + timestamp := uint64(utime.ToMilliseconds(parsedTime)) + c.setLastMessageTimestamp(timestamp) + c.evChan <- &SessionErrorEvent{ + SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "bugsnag", + Timestamp: timestamp, + Name: e.Exceptions[0].Message, + Payload: string(jsonEvent), + }, + } + } + + linkHeader := resp.Header.Get("Link") + if linkHeader == "" { + break + } + + nextLink := GetLinkFromAngularBrackets(linkHeader) + req.URL, err = url.Parse(nextLink) + if err != nil { + return err + } + } + return nil +} diff --git a/backend/services/integrations/integration/bugsnag.json b/backend/services/integrations/integration/bugsnag.json new file mode 100644 index 000000000..38db0a569 --- /dev/null +++ b/backend/services/integrations/integration/bugsnag.json @@ -0,0 +1,9207 @@ +[ + { + "id": "5e40ebc80056035588f90000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebc80056035588f90000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:08.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 608, + "method": "get_performance", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "605": " \"aggs\": {", + "606": " \"duration_avg\": {", + "607": " \"avg\": {", + "608": " \"field\": \"duration\"", + "609": " }", + "610": " }", + "611": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1398, + "method": "get_dashboard_performance", + "file": "/var/task/app.py", + "code": { + "1395": " args = dashboard.dashboard_args(params)", + "1396": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1397": " return {\"errors\": [\"unauthorized site\"]}", + "1398": " return {\"data\": dashboard.get_performance(site_id=siteId, **args)}", + "1399": "", + "1400": "", + "1401": "@app.route('/{siteId}/dashboard/performance/search', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.238.85", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebce0055f9426eac0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebce0055f9426eac0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:14.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1233, + "method": "get_missing_resources_trend", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "1230": " \"url_hostpath\": {", + "1231": " \"terms\": {", + "1232": " \"size\": 10,", + "1233": " \"field\": \"url_hostpath.raw\"", + "1234": " }", + "1235": " }", + "1236": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1481, + "method": "get_performance_sessions", + "file": "/var/task/app.py", + "code": { + "1478": " args = dashboard.dashboard_args(params)", + "1479": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1480": " return {\"errors\": [\"unauthorized site\"]}", + "1481": " return {\"data\": dashboard.get_missing_resources_trend(site_id=siteId, **args)}", + "1482": "", + "1483": "", + "1484": "@app.route('/{siteId}/dashboard/network', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.14.137", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebce005604d753340000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebce005604d753340000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:14.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 345, + "method": "__get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "342": " \"aggs\": {", + "343": " \"avg_img_load\": {", + "344": " \"avg\": {", + "345": " \"field\": \"duration\"", + "346": " }", + "347": " }", + "348": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 285, + "method": "get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "282": "def get_application_activity(site_id, startTimestamp=int(time.time()) - 24 * 60 * 60 * 1000,", + "283": " endTimestamp=int(time.time()) * 1000, platform=None, **args):", + "284": " with pg_client.PostgresClient() as cur:", + "285": " row = __get_application_activity(cur, site_id, startTimestamp, endTimestamp, platform)", + "286": " results = helper.variable_to_camel_case(row)", + "287": " print(\"new\")", + "288": " print(row)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1371, + "method": "get_dashboard_application_activity", + "file": "/var/task/app.py", + "code": { + "1368": " args = dashboard.dashboard_args(params)", + "1369": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1370": " return {\"errors\": [\"unauthorized site\"]}", + "1371": " return {\"data\": dashboard.get_application_activity(site_id=siteId, **args)}", + "1372": "", + "1373": "", + "1374": "@app.route('/{siteId}/dashboard/page_metrics', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.198.37", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebe40055e91b7de10000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebe40055e91b7de10000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:36.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 483, + "method": "get_slowest_images", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "480": " \"sort\": [", + "481": " {\"impact\": {\"order\": \"desc\"}}", + "482": " ],", + "483": " \"size\": 10", + "484": " }", + "485": " }", + "486": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1429, + "method": "get_dashboard_slowest_images", + "file": "/var/task/app.py", + "code": { + "1426": " args = dashboard.dashboard_args(params)", + "1427": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1428": " return {\"errors\": [\"unauthorized site\"]}", + "1429": " return {\"data\": dashboard.get_slowest_images(site_id=siteId, **args)}", + "1430": "", + "1431": "", + "1432": "@app.route('/{siteId}/dashboard/sessions_feedback', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.179.21", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebee0055ffd373510000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebee0055ffd373510000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:46.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 345, + "method": "__get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "342": " \"aggs\": {", + "343": " \"avg_img_load\": {", + "344": " \"avg\": {", + "345": " \"field\": \"duration\"", + "346": " }", + "347": " }", + "348": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 285, + "method": "get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "282": "def get_application_activity(site_id, startTimestamp=int(time.time()) - 24 * 60 * 60 * 1000,", + "283": " endTimestamp=int(time.time()) * 1000, platform=None, **args):", + "284": " with pg_client.PostgresClient() as cur:", + "285": " row = __get_application_activity(cur, site_id, startTimestamp, endTimestamp, platform)", + "286": " results = helper.variable_to_camel_case(row)", + "287": " print(\"new\")", + "288": " print(row)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1371, + "method": "get_dashboard_application_activity", + "file": "/var/task/app.py", + "code": { + "1368": " args = dashboard.dashboard_args(params)", + "1369": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1370": " return {\"errors\": [\"unauthorized site\"]}", + "1371": " return {\"data\": dashboard.get_application_activity(site_id=siteId, **args)}", + "1372": "", + "1373": "", + "1374": "@app.route('/{siteId}/dashboard/page_metrics', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.238.85", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebee0055e63104bf0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebee0055e63104bf0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:46.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 608, + "method": "get_performance", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "605": " \"aggs\": {", + "606": " \"duration_avg\": {", + "607": " \"avg\": {", + "608": " \"field\": \"duration\"", + "609": " }", + "610": " }", + "611": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1398, + "method": "get_dashboard_performance", + "file": "/var/task/app.py", + "code": { + "1395": " args = dashboard.dashboard_args(params)", + "1396": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1397": " return {\"errors\": [\"unauthorized site\"]}", + "1398": " return {\"data\": dashboard.get_performance(site_id=siteId, **args)}", + "1399": "", + "1400": "", + "1401": "@app.route('/{siteId}/dashboard/performance/search', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.152.29", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebee0055f40f4f3d0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebee0055f40f4f3d0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:46.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1233, + "method": "get_missing_resources_trend", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "1230": " \"url_hostpath\": {", + "1231": " \"terms\": {", + "1232": " \"size\": 10,", + "1233": " \"field\": \"url_hostpath.raw\"", + "1234": " }", + "1235": " }", + "1236": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1481, + "method": "get_performance_sessions", + "file": "/var/task/app.py", + "code": { + "1478": " args = dashboard.dashboard_args(params)", + "1479": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1480": " return {\"errors\": [\"unauthorized site\"]}", + "1481": " return {\"data\": dashboard.get_missing_resources_trend(site_id=siteId, **args)}", + "1482": "", + "1483": "", + "1484": "@app.route('/{siteId}/dashboard/network', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.52.5", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebee0055e63104c00000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebee0055e63104c00000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:46.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 483, + "method": "get_slowest_images", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "480": " \"sort\": [", + "481": " {\"impact\": {\"order\": \"desc\"}}", + "482": " ],", + "483": " \"size\": 10", + "484": " }", + "485": " }", + "486": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1429, + "method": "get_dashboard_slowest_images", + "file": "/var/task/app.py", + "code": { + "1426": " args = dashboard.dashboard_args(params)", + "1427": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1428": " return {\"errors\": [\"unauthorized site\"]}", + "1429": " return {\"data\": dashboard.get_slowest_images(site_id=siteId, **args)}", + "1430": "", + "1431": "", + "1432": "@app.route('/{siteId}/dashboard/sessions_feedback', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.9.29", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebf70055f2604b970000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebf70055f2604b970000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:55.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 345, + "method": "__get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "342": " \"aggs\": {", + "343": " \"avg_img_load\": {", + "344": " \"avg\": {", + "345": " \"field\": \"duration\"", + "346": " }", + "347": " }", + "348": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 285, + "method": "get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "282": "def get_application_activity(site_id, startTimestamp=int(time.time()) - 24 * 60 * 60 * 1000,", + "283": " endTimestamp=int(time.time()) * 1000, platform=None, **args):", + "284": " with pg_client.PostgresClient() as cur:", + "285": " row = __get_application_activity(cur, site_id, startTimestamp, endTimestamp, platform)", + "286": " results = helper.variable_to_camel_case(row)", + "287": " print(\"new\")", + "288": " print(row)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1371, + "method": "get_dashboard_application_activity", + "file": "/var/task/app.py", + "code": { + "1368": " args = dashboard.dashboard_args(params)", + "1369": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1370": " return {\"errors\": [\"unauthorized site\"]}", + "1371": " return {\"data\": dashboard.get_application_activity(site_id=siteId, **args)}", + "1372": "", + "1373": "", + "1374": "@app.route('/{siteId}/dashboard/page_metrics', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.238.85", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ebf70055f1cb952e0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ebf70055f1cb952e0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:36:55.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1233, + "method": "get_missing_resources_trend", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "1230": " \"url_hostpath\": {", + "1231": " \"terms\": {", + "1232": " \"size\": 10,", + "1233": " \"field\": \"url_hostpath.raw\"", + "1234": " }", + "1235": " }", + "1236": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1481, + "method": "get_performance_sessions", + "file": "/var/task/app.py", + "code": { + "1478": " args = dashboard.dashboard_args(params)", + "1479": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1480": " return {\"errors\": [\"unauthorized site\"]}", + "1481": " return {\"data\": dashboard.get_missing_resources_trend(site_id=siteId, **args)}", + "1482": "", + "1483": "", + "1484": "@app.route('/{siteId}/dashboard/network', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.179.21", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ec480055f7dc02080000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ec480055f7dc02080000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:38:16.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 345, + "method": "__get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "342": " \"aggs\": {", + "343": " \"avg_img_load\": {", + "344": " \"avg\": {", + "345": " \"field\": \"duration\"", + "346": " }", + "347": " }", + "348": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 285, + "method": "get_application_activity", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "282": "def get_application_activity(site_id, startTimestamp=int(time.time()) - 24 * 60 * 60 * 1000,", + "283": " endTimestamp=int(time.time()) * 1000, platform=None, **args):", + "284": " with pg_client.PostgresClient() as cur:", + "285": " row = __get_application_activity(cur, site_id, startTimestamp, endTimestamp, platform)", + "286": " results = helper.variable_to_camel_case(row)", + "287": " print(\"new\")", + "288": " print(row)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1371, + "method": "get_dashboard_application_activity", + "file": "/var/task/app.py", + "code": { + "1368": " args = dashboard.dashboard_args(params)", + "1369": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1370": " return {\"errors\": [\"unauthorized site\"]}", + "1371": " return {\"data\": dashboard.get_application_activity(site_id=siteId, **args)}", + "1372": "", + "1373": "", + "1374": "@app.route('/{siteId}/dashboard/page_metrics', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.52.5", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ec480055f40f9e8b0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ec480055f40f9e8b0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:38:16.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 608, + "method": "get_performance", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "605": " \"aggs\": {", + "606": " \"duration_avg\": {", + "607": " \"avg\": {", + "608": " \"field\": \"duration\"", + "609": " }", + "610": " }", + "611": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1398, + "method": "get_dashboard_performance", + "file": "/var/task/app.py", + "code": { + "1395": " args = dashboard.dashboard_args(params)", + "1396": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1397": " return {\"errors\": [\"unauthorized site\"]}", + "1398": " return {\"data\": dashboard.get_performance(site_id=siteId, **args)}", + "1399": "", + "1400": "", + "1401": "@app.route('/{siteId}/dashboard/performance/search', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.179.21", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ec480056027165220000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ec480056027165220000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:38:16.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1233, + "method": "get_missing_resources_trend", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "1230": " \"url_hostpath\": {", + "1231": " \"terms\": {", + "1232": " \"size\": 10,", + "1233": " \"field\": \"url_hostpath.raw\"", + "1234": " }", + "1235": " }", + "1236": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1481, + "method": "get_performance_sessions", + "file": "/var/task/app.py", + "code": { + "1478": " args = dashboard.dashboard_args(params)", + "1479": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1480": " return {\"errors\": [\"unauthorized site\"]}", + "1481": " return {\"data\": dashboard.get_missing_resources_trend(site_id=siteId, **args)}", + "1482": "", + "1483": "", + "1484": "@app.route('/{siteId}/dashboard/network', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.9.29", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40ec480055ef78f0130000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40ec480055ef78f0130000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:38:16.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 483, + "method": "get_slowest_images", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "480": " \"sort\": [", + "481": " {\"impact\": {\"order\": \"desc\"}}", + "482": " ],", + "483": " \"size\": 10", + "484": " }", + "485": " }", + "486": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1429, + "method": "get_dashboard_slowest_images", + "file": "/var/task/app.py", + "code": { + "1426": " args = dashboard.dashboard_args(params)", + "1427": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1428": " return {\"errors\": [\"unauthorized site\"]}", + "1429": " return {\"data\": dashboard.get_slowest_images(site_id=siteId, **args)}", + "1430": "", + "1431": "", + "1432": "@app.route('/{siteId}/dashboard/sessions_feedback', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.198.37", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e40efe90055f6b0f1a70000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e40efe90055f6b0f1a70000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e20046253437b0019934804", + "received_at": "2020-02-10T05:53:45.000Z", + "exceptions": [ + { + "error_class": "Exception", + "message": "NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "stacktrace": [ + { + "column_number": null, + "in_project": false, + "line_number": 181, + "method": "_raise_error", + "file": "/var/task/elasticsearch/connection/base.py", + "code": { + "178": " logger.warning(\"Undecodable raw error response from server: %s\", err)", + "179": "", + "180": " raise HTTP_EXCEPTIONS.get(status_code, TransportError)(", + "181": " status_code, error_message, additional_info", + "182": " )", + "183": "", + "184": " def _get_default_user_agent(self):" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 156, + "method": "perform_request", + "file": "/var/task/elasticsearch/connection/http_requests.py", + "code": { + "153": " response.status_code,", + "154": " raw_data,", + "155": " )", + "156": " self._raise_error(response.status_code, raw_data)", + "157": "", + "158": " self.log_request_success(", + "159": " method," + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 350, + "method": "perform_request", + "file": "/var/task/elasticsearch/transport.py", + "code": { + "347": " body,", + "348": " headers=headers,", + "349": " ignore=ignore,", + "350": " timeout=timeout,", + "351": " )", + "352": "", + "353": " except TransportError as e:" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 819, + "method": "search", + "file": "/var/task/elasticsearch/client/__init__.py", + "code": { + "816": " if not index:", + "817": " index = \"_all\"", + "818": " return self.transport.perform_request(", + "819": " \"GET\", _make_path(index, \"_search\"), params=params, body=body", + "820": " )", + "821": "", + "822": " @query_params(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 84, + "method": "_wrapped", + "file": "/var/task/elasticsearch/client/utils.py", + "code": { + "81": " for p in (\"ignore\", \"request_timeout\"):", + "82": " if p in kwargs:", + "83": " params[p] = kwargs.pop(p)", + "84": " return func(*args, params=params, **kwargs)", + "85": "", + "86": " return _wrapped", + "87": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 58, + "method": "get_agg", + "file": "/var/task/chalicelib/utils/es_client.py", + "code": { + "54": " data = self.__es.search(", + "55": " index=index,", + "56": " scroll='2m',", + "57": " size=1000,", + "58": " body=query", + "59": " )", + "60": " return data[\"aggregations\"]" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 608, + "method": "get_performance", + "file": "/var/task/chalicelib/dashboard.py", + "code": { + "605": " \"aggs\": {", + "606": " \"duration_avg\": {", + "607": " \"avg\": {", + "608": " \"field\": \"duration\"", + "609": " }", + "610": " }", + "611": " }" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 1398, + "method": "get_dashboard_performance", + "file": "/var/task/app.py", + "code": { + "1395": " args = dashboard.dashboard_args(params)", + "1396": " if not sites.is_authorized(site_id=siteId, tenant_id=context[\"tenantId\"]):", + "1397": " return {\"errors\": [\"unauthorized site\"]}", + "1398": " return {\"data\": dashboard.get_performance(site_id=siteId, **args)}", + "1399": "", + "1400": "", + "1401": "@app.route('/{siteId}/dashboard/performance/search', methods=['GET'])" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 158, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "155": " # args['context'] = authorizer_context", + "156": "", + "157": " try:", + "158": " r = view_func(**args)", + "159": " pg_client.close()", + "160": " except Exception as e:", + "161": " pg_client.close()" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 168, + "method": "_view_func", + "file": "/var/task/app.py", + "code": { + "165": " scope.set_tag('asayer_session_id', app.current_request.headers.get('vnd.asayer.io.sid'))", + "166": " scope.set_extra(\"context\", args['context'])", + "167": " sentry_sdk.capture_exception(e)", + "168": " raise e", + "169": "", + "170": " return r", + "171": "" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": null, + "in_project": false, + "line_number": 731, + "method": "_get_view_function_response", + "file": "/var/task/chalice/app.py", + "code": { + "728": "", + "729": " def _get_view_function_response(self, view_function, function_args):", + "730": " try:", + "731": " response = view_function(**function_args)", + "732": " if not isinstance(response, Response):", + "733": " response = Response(body=response)", + "734": " self._validate_response(response)" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "special_info": { + "asayerSessionId": "525314475541266774" + }, + "environment": {}, + "session": {}, + "extraData": {} + }, + "customDiagnostics": {}, + "request": {}, + "app": { + "releaseStage": "production", + "version": null + }, + "device": { + "hostname": "169.254.9.29", + "runtimeVersions": { + "python": "3.6.10" + } + }, + "user": {}, + "breadcrumbs": [], + "context": "/var/task/elasticsearch/connection/base.py:181", + "severity": "warning", + "unhandled": false + }, + { + "id": "5e411c8b0055f891aaa90000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e411c8b0055f891aaa90000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T09:04:11.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e411cc00055e23d4cf60000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e411cc00055e23d4cf60000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T09:05:04.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T09:04:11.258Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T09:04:12.373Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/filters" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T09:04:13.599Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "DIV.ui.icon.input.autoComplete_searchInput_2Jy11OB > INPUT:nth-child(1)" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T09:04:14.508Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T09:04:14.684Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T09:04:14.817Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T09:04:17.302Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/events/search?type=CLICK&q=log" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T09:04:18.951Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T09:04:20.066Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T09:04:20.353Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T09:04:28.368Z", + "metaData": { + "targetText": "Login", + "targetSelector": "DIV.filterItem_filterItem_198AqGF:nth-child(3)" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T09:04:30.658Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T09:04:30.949Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T09:04:33.684Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T09:04:36.655Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T09:05:03.190Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T09:05:04.485Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412dc60055ed91d47b0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412dc60055ed91d47b0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:17:42.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(4) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412e330056040fdf1a0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412e330056040fdf1a0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:19:31.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(4) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:17:42.601Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:17:43.512Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/filters" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T10:17:44.380Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T10:17:44.791Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T10:17:44.966Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "log", + "name": "Console output", + "timestamp": "2020-02-10T10:17:45.281Z", + "metaData": { + "severity": "log", + "[0]": "[object Object]" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:17:47.278Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/events/search?type=LOCATION&q=runs" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:17:47.812Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:17:48.654Z", + "metaData": { + "targetText": "/runs", + "targetSelector": "DIV.filterItem_filterItem_198AqGF:nth-child(2)" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:17:50.958Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:17:51.290Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:17:56.351Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:18:06.784Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:18:36.785Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:19:07.276Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:19:22.671Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:19:28.025Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:19:31.408Z", + "metaData": { + "targetText": "Referrer", + "targetSelector": "DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(4) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412ed00055f6e66b350000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412ed00055f6e66b350000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:08.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:20:43.394Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:20:49.493Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:07.122Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:36.741Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:21:46.273Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "BUTTON.eventEditor_button_3jCuBfU:nth-child(2) > SPAN.icon_wrapper_2jeksFN.fill-gray-medium > svg" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:48.430Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:48.730Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:54.910Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:21:59.604Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:03.994Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:22:06.686Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.074Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.964Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412ed300560576e5e50000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412ed300560576e5e50000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:11.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:20:43.394Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:20:49.493Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:07.122Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:36.741Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:21:46.273Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "BUTTON.eventEditor_button_3jCuBfU:nth-child(2) > SPAN.icon_wrapper_2jeksFN.fill-gray-medium > svg" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:48.430Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:48.730Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:54.910Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:21:59.604Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:03.994Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:22:06.686Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.074Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.964Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:08.006Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:09.371Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:11.796Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412ed60055e9547d230000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412ed60055e9547d230000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:14.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r SPAN.icon_wrapper_2jeksFN.fill-gray-medium > svg" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:48.430Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:48.730Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:54.910Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:21:59.604Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:03.994Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:22:06.686Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.074Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.964Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:08.006Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:09.371Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:11.796Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:11.840Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:12.624Z", + "metaData": { + "targetText": "LIVE (2)Past 7 DaysTodayYesterdayPast 7 DaysPast 30 DaysThis MonthPrevious MonthThis YearCustom RangeIssuesMissing ResourceRage ClickSl(...)", + "targetSelector": "DIV.container-70" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.123Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.906Z", + "metaData": { + "targetText": "Device", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412ed70055e8a5044c0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412ed70055e8a5044c0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:15.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r SPAN.icon_wrapper_2jeksFN.fill-gray-medium > svg" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:21:48.430Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:48.730Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:21:54.910Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:21:59.604Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:03.994Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:22:06.686Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.074Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.964Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:08.006Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:09.371Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:11.796Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:11.840Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:12.624Z", + "metaData": { + "targetText": "LIVE (2)Past 7 DaysTodayYesterdayPast 7 DaysPast 30 DaysThis MonthPrevious MonthThis YearCustom RangeIssuesMissing ResourceRage ClickSl(...)", + "targetSelector": "DIV.container-70" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.123Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.906Z", + "metaData": { + "targetText": "Device", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:13.939Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:14.796Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:15.482Z", + "metaData": { + "targetText": "Browser", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412ed90055ebb627250000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412ed90055ebb627250000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:17.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:03.994Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:22:06.686Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.074Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.964Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:08.006Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:09.371Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:11.796Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:11.840Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:12.624Z", + "metaData": { + "targetText": "LIVE (2)Past 7 DaysTodayYesterdayPast 7 DaysPast 30 DaysThis MonthPrevious MonthThis YearCustom RangeIssuesMissing ResourceRage ClickSl(...)", + "targetSelector": "DIV.container-70" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.123Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.906Z", + "metaData": { + "targetText": "Device", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:13.939Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:14.796Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:15.482Z", + "metaData": { + "targetText": "Browser", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:15.533Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:16.308Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:17.634Z", + "metaData": { + "targetText": "Country", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412edb0055ea9350dd0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412edb0055ea9350dd0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:19.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:07.964Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:08.006Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:09.371Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:11.796Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:11.840Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:12.624Z", + "metaData": { + "targetText": "LIVE (2)Past 7 DaysTodayYesterdayPast 7 DaysPast 30 DaysThis MonthPrevious MonthThis YearCustom RangeIssuesMissing ResourceRage ClickSl(...)", + "targetSelector": "DIV.container-70" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.123Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.906Z", + "metaData": { + "targetText": "Device", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:13.939Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:14.796Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:15.482Z", + "metaData": { + "targetText": "Browser", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:15.533Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:16.308Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:17.634Z", + "metaData": { + "targetText": "Country", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:17.670Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:18.450Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:19.161Z", + "metaData": { + "targetText": "Duration", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412ee10055ec653dbf0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412ee10055ec653dbf0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:25.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:08.006Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:09.371Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:11.796Z", + "metaData": { + "targetText": "OS", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:11.840Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:12.624Z", + "metaData": { + "targetText": "LIVE (2)Past 7 DaysTodayYesterdayPast 7 DaysPast 30 DaysThis MonthPrevious MonthThis YearCustom RangeIssuesMissing ResourceRage ClickSl(...)", + "targetSelector": "DIV.container-70" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.123Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.906Z", + "metaData": { + "targetText": "Device", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:13.939Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:14.796Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:15.482Z", + "metaData": { + "targetText": "Browser", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:15.533Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:16.308Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:17.634Z", + "metaData": { + "targetText": "Country", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:17.670Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:18.450Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:19.161Z", + "metaData": { + "targetText": "Duration", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:19.197Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:22.056Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:25.556Z", + "metaData": { + "targetText": "email", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(3) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e412eeb0055f714b5290000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e412eeb0055f714b5290000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:22:35.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:13.906Z", + "metaData": { + "targetText": "Device", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:13.939Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:14.796Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:15.482Z", + "metaData": { + "targetText": "Browser", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:15.533Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:16.308Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:17.634Z", + "metaData": { + "targetText": "Country", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:17.670Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:18.450Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:19.161Z", + "metaData": { + "targetText": "Duration", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5 > DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:19.197Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:22.056Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:25.556Z", + "metaData": { + "targetText": "email", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(3) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(3) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:22:25.596Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Cannot read property '0' of undefined", + "severity": "error" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:27.908Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:30.132Z", + "metaData": { + "targetText": "ADD STEP", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV:nth-child(1) > BUTTON.ui.button.search-bottom-button.button_plain_2pVBxaE.button_button_2rl5k6p" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:22:35.217Z", + "metaData": { + "targetText": "Console Errors", + "targetSelector": "DIV.bugFinder_bottom_3SBJs2c > DIV.customFilters_wrapper_wkzfriO:nth-child(1) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(1) > DIV.filterItem_filterItem_198AqGF > SPAN.filterItem_label_26N8IUB:nth-child(2)" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e41330d0055ed96770b0000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e41330d0055ed96770b0000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:40:13.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV.sessionItem_playLink_3KWWOLv:nth-child(2) > A.link_link_3wNogtO > SPAN.icon_wrapper_2jeksFN.fill-teal > svg" + } + }, + { + "type": "navigation", + "name": "History pushState", + "timestamp": "2020-02-10T10:39:41.323Z", + "metaData": { + "title": null, + "state": { + "key": "z188uo" + }, + "prevState": { + "key": "x8h7ck" + }, + "to": "/0/live/session/525627733332840073", + "from": "/0/sessions" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:41.867Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/integrations/slack/channels" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:41.868Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/integrations/jiracloud" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:39:47.121Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:39:48.083Z", + "metaData": { + "targetText": "Sessions", + "targetSelector": "A.playerBlockHeader_backLink_3-eqyfs.link_link_3wNogtO" + } + }, + { + "type": "navigation", + "name": "History pushState", + "timestamp": "2020-02-10T10:39:48.083Z", + "metaData": { + "title": null, + "state": { + "key": "068d67" + }, + "prevState": { + "key": "z188uo" + }, + "to": "/0/sessions", + "from": "/0/live/session/525627733332840073" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:48.724Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions2/favorite" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:48.729Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/integration/sources" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:48.731Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/integration/variables" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:48.731Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/0/sessions/live" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:39:48.733Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:39:48.927Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/0/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:39:49.239Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:39:53.846Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:39:55.619Z", + "metaData": { + "targetText": "app.asayer.ioapp.asayer.io104.155.66.82www.mynexity.frnexity.frmonbanquet.frSessionsTestsRunsInsightsGood Job!You have discovered 100% (...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:39:58.665Z", + "metaData": { + "targetText": "Load more...", + "targetSelector": "BUTTON.ui.button.button_button_2rl5k6p.button_outline_2i2l28b" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:40:02.865Z", + "metaData": { + "targetText": "Find sessions with Input", + "targetSelector": "DIV.randomPlaceholder_placeholder_3CSat_L" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:40:08.654Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:40:12.598Z", + "metaData": { + "targetText": "Country", + "targetSelector": "DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(4) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(3) > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/0/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e4137080055f537dfa40000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e4137080055f537dfa40000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e4137081b4d7f0019be2d46", + "received_at": "2020-02-10T10:57:12.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Expected [K, V] tuple: Try Asayer", + "stacktrace": [ + { + "column_number": 19696, + "in_project": null, + "line_number": 6, + "method": "Pe", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "))},i}function De(e,t){return e===t?e:x(e)?t:e.constructor(t)}function Pe(e){if(e!==Object(e))throw new TypeError(\"Expected [K, V] tuple: \"+e)}function Ae(e){return v(e)?b:m(e)?w:_}function Ne(e){retu" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 13469, + "in_project": null, + "line_number": 6, + "method": "", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "eq()},t.prototype.__iterate=function(e,t){var n=this;return this._iter.__iterate((function(t){if(t){Pe(t);var r=h(t);return e(r?t.get(1):t[1],r?t.get(0):t[0],n)}}),t)},t.prototype.__iterator=function(" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 35265, + "in_project": null, + "line_number": 6, + "method": "t.__iterate", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": ")}))},t.prototype.__iterate=function(e,t){for(var n,r=t?this.size:0,i=Kt(this,t);(n=i())!==Gt&&!1!==e(n,t?--r:r++,this););return r},t.prototype.__ensureOwner=function(e){return e===this.__ownerID?this" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 13440, + "in_project": null, + "line_number": 6, + "method": "t.__iterate", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "ction(){return this._iter.toSeq()},t.prototype.__iterate=function(e,t){var n=this;return this._iter.__iterate((function(t){if(t){Pe(t);var r=h(t);return e(r?t.get(1):t[1],r?t.get(0):t[0],n)}}),t)},t.p" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 51338, + "in_project": null, + "line_number": 6, + "method": "t.forEach", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "n(e,t,n){var r=this.findEntry(e,t);return r?r[1]:n},forEach:function(e,t){return Be(this.size),this.__iterate(t?e.bind(t):e)},join:function(e){Be(this.size),e=void 0!==e?\"\"+e:\",\";var t=\"\",n=!0;return " + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 24768, + "in_project": null, + "line_number": 6, + "method": "", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "tion t(t){return null==t?Pt():X(t)&&!S(t)?t:Pt().withMutations((function(n){var r=e(t);Be(r.size),r.forEach((function(e,t){return n.set(t,e)}))}))}return e&&(t.__proto__=e),t.prototype=Object.create(e" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 24340, + "in_project": null, + "line_number": 6, + "method": "t.mt [as withMutations]", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "];return $e(this,e,Pt(),(function(e){return lt(e,t)}))}function mt(e){var t=this.asMutable();return e(t),t.wasAltered()?t.__ensureOwner(this.__ownerID):this}function yt(){return this.__ownerID?this:th" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 24717, + "in_project": null, + "line_number": 6, + "method": "t [as constructor]", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "ge.prototype.cacheResult=Ie;var wt=function(e){function t(t){return null==t?Pt():X(t)&&!S(t)?t:Pt().withMutations((function(n){var r=e(t);Be(r.size),r.forEach((function(e,t){return n.set(t,e)}))}))}re" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 22884, + "in_project": null, + "line_number": 6, + "method": "ot", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "on(e){return e===r?t:n(e,t,i)}))}:function(t,n){e.set(n,t)},o=0;o0;)t[n]=arguments[n+1];retur" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 22374, + "in_project": null, + "line_number": 6, + "method": "t.rt", + "file": "https://app.asayer.io/1.app-531e376.js", + "code": { + "6": "){return $e(this,e,t,n)}function rt(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return ot(this,e)}function it(e){for(var t=[],n=arguments.length-1;n-- >0;)t[n]=arguments[n+1];if(\"function" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + } + ] + } + ], + "threads": [], + "metaData": { + "device": { + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" + } + }, + "customDiagnostics": {}, + "request": { + "url": "https://app.asayer.io/72/sessions", + "clientIp": "185.64.149.99" + }, + "app": { + "releaseStage": "production" + }, + "device": { + "locale": "fr-FR", + "time": "2020-02-10T10:57:12.038Z", + "osName": "Windows 10.0", + "browserName": "Chrome", + "browserVersion": "79.0.3945" + }, + "user": { + "id": "185.64.149.99" + }, + "breadcrumbs": [ + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:00.406Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/events/search?q=try%20as" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:03.720Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "DIV.sessionItem_sessionItem_1a0toO6:nth-child(2) > DIV.sessionItem_playLink_3KWWOLv:nth-child(2) > A.link_link_3wNogtO > SPAN.icon_wrapper_2jeksFN.fill-teal > svg" + } + }, + { + "type": "navigation", + "name": "History pushState", + "timestamp": "2020-02-10T10:57:03.732Z", + "metaData": { + "title": null, + "state": { + "key": "zw6xmd" + }, + "prevState": { + "key": "olgtps" + }, + "to": "/72/session/521925111024389735", + "from": "/72/sessions" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:04.022Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/integrations/slack/channels" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:04.145Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/sessions2/521925111024389735" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:57:04.302Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:04.415Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/integrations/jiracloud" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:04.449Z", + "metaData": { + "status": 200, + "request": "GET https://asayer-sessions-mobs.s3.amazonaws.com/72/521925111024389735.mob?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA6RAO3SOP7M3VQ76X%2F20200210%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20200210T105704Z&X-Amz-Expires=100000&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEFoaDGV1LWNlbnRyYWwtMSJHMEUCIEVe1WqkCTz4KIsdtiy2gqovOU%2B0ob%2FnonddeM3rR%2BQsAiEA17YmEYbn1LyP3pTgvVkeOIf8rvzg%2FuDsmU6xeRhZ0YMqyQEIExAAGgw5OTg2MTEwNjM3MTEiDOKUXz48dwdOjJOn0SqmAdsMmXq3Iiwo6JQGrFVkAIbIEKNnmrx9LnqEKrUWNzOK%2FdIkpzcSU3%2BOmZv2bBPVWMOkSlE61niH7JDPknexq03YMHrX9c1rTNvmd0amnORfIHomk%2FnEm2mddbb0YTG%2FmEAXTRw4ihLki9G06Skhenx%2BVAW4RlJtsIjgxiCMks55V06VTuha%2B%2BF%2FirITPIC4MnxbmNtHKtlAmWjGvDeEwq2rxamMkfQw6tqE8gU64AH4kxvtNVO%2FOQIHhEvyhAvoh82pmOjx0L0HeH5%2BeN1YZKO5%2FbCbIBTcwr5%2B0X%2BugKTAet0ya9O%2F8t5y%2BKb5dfriLV7AEwdmyFztdzNiv95bY9UkwEtrTUyMprX%2BPojz3QAFxnrKR%2Bzpd7%2FBDlWI2cdoEHK9yukmyNS0Ln7NOilOhRFwO1edwVdbkM3vmARUu4TQBVSLn9wdhBm5Fc%2FUoOTYrZHstQ0w6fp5a4CMaf2OEx8oxKoaAthtEvSnI0ReTqWY0iQMrOUBHOAAj9PTva%2B4Iv95PaNklDkfWCEMtWleNg%3D%3D&X-Amz-Signature=5b97d72871d43a4a43bf3732149a4b17ced2f324db17c27d8dbea5a9dae0f2ec" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:07.216Z", + "metaData": { + "targetText": "Sessions", + "targetSelector": "A.playerBlockHeader_backLink_3-eqyfs.link_link_3wNogtO > DIV:nth-child(2)" + } + }, + { + "type": "navigation", + "name": "History pushState", + "timestamp": "2020-02-10T10:57:07.216Z", + "metaData": { + "title": null, + "state": { + "key": "iq3oi2" + }, + "prevState": { + "key": "zw6xmd" + }, + "to": "/72/sessions", + "from": "/72/session/521925111024389735" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.561Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/sessions2/favorite" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.562Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/integration/sources" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.563Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/integration/variables" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:57:07.710Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.862Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/72/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:57:08.185Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:08.791Z", + "metaData": { + "targetText": "Find sessions with Click", + "targetSelector": "DIV.randomPlaceholder_placeholder_3CSat_L" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:10.177Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "DIV.ui.fluid.left.icon.input.eventFilter_searchField_2MpErPW > INPUT:nth-child(1)" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:11.279Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/events/search?q=try%20asa" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:11.922Z", + "metaData": { + "targetText": "Try Asayer", + "targetSelector": "DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/72/sessions", + "severity": "error", + "unhandled": true + }, + { + "id": "5e41370e00560395da120000", + "url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227/events/5e41370e00560395da120000", + "project_url": "https://api.bugsnag.com/projects/5d00452ccbe86e001631f227", + "is_full_report": true, + "error_id": "5e399adc2a024a001971c551", + "received_at": "2020-02-10T10:57:18.000Z", + "exceptions": [ + { + "error_class": "TypeError", + "message": "Cannot read property '0' of undefined", + "stacktrace": [ + { + "column_number": 307952, + "in_project": null, + "line_number": 1, + "method": "t.n.onFilterClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "applyFilter,300),n.onFilterClick=function(e,t){n.addFilter(e),n.props.setFilterOption(e.key,[e.value[0]]),(t||e.hasNoValue)&&n.applyFilter()},n.addFilter=function(e){var t=n.props,r=t.index,o=t.filter" + }, + "macho_uuid": null, + "source_control_link": null, + "source_control_name": "" + }, + { + "column_number": 309878, + "in_project": null, + "line_number": 1, + "method": "onClick", + "file": "https://app.asayer.io/app-c093b08.js", + "code": { + "1": "r n=this;return a.a.createElement(b.a,{label:t.label||t.key,icon:t.icon,onClick:function(){return n.onFilterClick(t)}})}},{key:\"renderList\",value:function(e,t){for(var n=[],r=0;r DIV:nth-child(2)" + } + }, + { + "type": "navigation", + "name": "History pushState", + "timestamp": "2020-02-10T10:57:07.216Z", + "metaData": { + "title": null, + "state": { + "key": "iq3oi2" + }, + "prevState": { + "key": "zw6xmd" + }, + "to": "/72/sessions", + "from": "/72/session/521925111024389735" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.561Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/sessions2/favorite" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.562Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/integration/sources" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.563Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/integration/variables" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:57:07.710Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:07.862Z", + "metaData": { + "status": 200, + "request": "POST https://parrot.asayer.io/72/sessions/search2" + } + }, + { + "type": "request", + "name": "XMLHttpRequest succeeded", + "timestamp": "2020-02-10T10:57:08.185Z", + "metaData": { + "status": 200, + "request": "POST https://api.amplitude.com" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:08.791Z", + "metaData": { + "targetText": "Find sessions with Click", + "targetSelector": "DIV.randomPlaceholder_placeholder_3CSat_L" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:10.177Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "DIV.ui.fluid.left.icon.input.eventFilter_searchField_2MpErPW > INPUT:nth-child(1)" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:11.279Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/events/search?q=try%20asa" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:11.922Z", + "metaData": { + "targetText": "Try Asayer", + "targetSelector": "DIV.filterItem_filterItem_198AqGF" + } + }, + { + "type": "error", + "name": "TypeError", + "timestamp": "2020-02-10T10:57:12.038Z", + "metaData": { + "errorClass": "TypeError", + "errorMessage": "Expected [K, V] tuple: Try Asayer", + "severity": "error" + } + }, + { + "type": "request", + "name": "fetch() succeeded", + "timestamp": "2020-02-10T10:57:12.161Z", + "metaData": { + "status": 200, + "request": "GET https://parrot.asayer.io/72/filters" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:14.201Z", + "metaData": { + "targetText": "asayer.ioasayer.ioSessionsInsightsFew more steps and you’re done!You have discovered 83% of Asayer features!Discover more of AsayerInst(...)", + "targetSelector": "DIV#app" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:15.103Z", + "metaData": { + "targetText": "(...)", + "targetSelector": "DIV.filterSelectionButton_wrapper_3asjaf8" + } + }, + { + "type": "user", + "name": "UI click", + "timestamp": "2020-02-10T10:57:18.460Z", + "metaData": { + "targetText": "Clicked", + "targetSelector": "DIV.customFilters_wrapper_wkzfriO:nth-child(2) > DIV.filterModal_modal_CKdnaaM:nth-child(2) > DIV > DIV.filterModal_filterListStatic_3QeEoBa:nth-child(2) > DIV.filterModal_filterGroup_1dsFuXp.mr-6.mb-6:nth-child(2) > DIV.filterModal_list_3AV7i2N:nth-child(2) > DIV.mr-5:nth-child(2) > DIV.filterItem_filterItem_198AqGF" + } + } + ], + "context": "/72/sessions", + "severity": "error", + "unhandled": true + } +] \ No newline at end of file diff --git a/backend/services/integrations/integration/client.go b/backend/services/integrations/integration/client.go new file mode 100644 index 000000000..3786f4324 --- /dev/null +++ b/backend/services/integrations/integration/client.go @@ -0,0 +1,153 @@ +package integration + +import ( + "sync" + "fmt" + "encoding/json" + + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/pkg/utime" +) + +const MAX_ATTEMPTS_IN_A_ROW = 4 +const MAX_ATTEMPTS = 40 +const ATTEMPTS_INTERVAL = 3 * 60 * 60 * 1000 + +type requester interface { + Request(*client) error +} + +type requestData struct { + LastMessageTimestamp uint64 // `json:"lastMessageTimestamp, string"` + LastMessageId string + UnsuccessfullAttemptsCount int + LastAttemptTimestamp int64 +} + +type client struct { + requestData + requester + integration *postgres.Integration + // TODO: timeout ? + mux sync.Mutex + updateChan chan<- postgres.Integration + evChan chan<- *SessionErrorEvent + errChan chan<- error +} + +type SessionErrorEvent struct { + SessionID uint64 + Token string + *messages.RawErrorEvent +} + +type ClientMap map[ string ]*client + +func NewClient(i *postgres.Integration, updateChan chan<- postgres.Integration, evChan chan<- *SessionErrorEvent, errChan chan<- error) (*client, error) { + c := new(client) + if err := c.Update(i); err != nil { + return nil, err + } + + if err := json.Unmarshal(i.RequestData, &c.requestData); err != nil { + return nil, err + } + c.evChan = evChan + c.errChan = errChan + c.updateChan = updateChan + // TODO: RequestData manager + if c.requestData.LastMessageTimestamp == 0 { + // ? + c.requestData.LastMessageTimestamp = uint64(utime.CurrentTimestamp() - 24*60*60*1000) + } + + return c, nil +} + + +// from outside +func (c* client) Update(i *postgres.Integration) error { + c.mux.Lock() + defer c.mux.Unlock() + var r requester + switch i.Provider { + case "bugsnag": + r = new(bugsnag) + case "cloudwatch": + r = new(cloudwatch) + case "datadog": + r = new(datadog) + case "elasticsearch": + r = new(elasticsearch) + case "newrelic": + r = new(newrelic) + case "rollbar": + r = new(rollbar) + case "sentry": + r = new(sentry) + case "stackdriver": + r = new(stackdriver) + case "sumologic": + r = new(sumologic) + } + if err := json.Unmarshal(i.Options, r); err != nil { + return err + } + c.integration = i + c.requester = r + return nil +} + +// package scope +func (c *client) setLastMessageTimestamp(timestamp uint64) { + if timestamp > c.requestData.LastMessageTimestamp { + c.requestData.LastMessageTimestamp = timestamp + } +} +func (c *client) getLastMessageTimestamp() uint64 { + return c.requestData.LastMessageTimestamp +} +func (c *client) setLastMessageId(timestamp uint64, id string) { + //if timestamp >= c.requestData.LastMessageTimestamp { + c.requestData.LastMessageId = id + c.requestData.LastMessageTimestamp = timestamp + //} +} +func (c *client) getLastMessageId() string { + return c.requestData.LastMessageId +} + +func (c *client) handleError(err error) { + c.errChan <- fmt.Errorf("%v | Integration: %v", err, *c.integration) +} + +// Thread-safe +func (c *client) Request() { + c.mux.Lock() + defer c.mux.Unlock() + if c.requestData.UnsuccessfullAttemptsCount >= MAX_ATTEMPTS || + (c.requestData.UnsuccessfullAttemptsCount >= MAX_ATTEMPTS_IN_A_ROW && + utime.CurrentTimestamp() - c.requestData.LastAttemptTimestamp < ATTEMPTS_INTERVAL) { + return + } + + c.requestData.LastAttemptTimestamp = utime.CurrentTimestamp() + err := c.requester.Request(c) + if err != nil { + c.handleError(err) + c.requestData.UnsuccessfullAttemptsCount++; + } else { + c.requestData.UnsuccessfullAttemptsCount = 0 + } + rd, err := json.Marshal(c.requestData) + if err != nil { + c.handleError(err) + } + // RequestData is a byte array (pointer-like type), but it's replacement + // won't affect the previous value sent by channel + c.integration.RequestData = rd + c.updateChan <- *c.integration +} + + diff --git a/backend/services/integrations/integration/cloudwatch.go b/backend/services/integrations/integration/cloudwatch.go new file mode 100644 index 000000000..fa2210138 --- /dev/null +++ b/backend/services/integrations/integration/cloudwatch.go @@ -0,0 +1,89 @@ +package integration + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + + "strings" + "regexp" + "openreplay/backend/pkg/messages" +) + + +var reIsException = regexp.MustCompile(`(?i)exception|error`) + +type cloudwatch struct { + AwsAccessKeyId string // `json:"aws_access_key_id"` + AwsSecretAccessKey string // `json:"aws_secret_access_key"` + LogGroupName string // `json:"log_group_name"` + Region string // `json:"region"` +} + + +func (cw *cloudwatch) Request(c *client) error { + startTs := int64(c.getLastMessageTimestamp() + 1) // From next millisecond + //endTs := utils.CurrentTimestamp() + sess, err := session.NewSession(aws.NewConfig(). + WithRegion(cw.Region). + WithCredentials( + credentials.NewStaticCredentials(cw.AwsAccessKeyId, cw.AwsSecretAccessKey, ""), + ), + ) + if err != nil { + return err + } + svc := cloudwatchlogs.New(sess) + + + filterOptions := new(cloudwatchlogs.FilterLogEventsInput). + SetStartTime(startTs). // Inclusively both startTime and endTime + // SetEndTime(endTs). // Default nil? + // SetLimit(10000). // Default 10000 + SetLogGroupName(cw.LogGroupName). + SetFilterPattern("openReplaySessionToken") + //SetFilterPattern("asayer_session_id") + + for { + output, err := svc.FilterLogEvents(filterOptions) + if err != nil { + return err + } + for _, e := range output.Events { + if e.Message == nil || e.Timestamp == nil { + continue + } + if !reIsException.MatchString(*e.Message) { // too weak condition ? + continue + } + token, err := GetToken(*e.Message) + if err != nil { + c.errChan <- err + continue + } + name := "" + if e.LogStreamName != nil { + name = *e.LogStreamName + } + timestamp := uint64(*e.Timestamp) + c.setLastMessageTimestamp(timestamp) + c.evChan <- &SessionErrorEvent{ + //SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "cloudwatch", + Timestamp: timestamp, // e.IngestionTime ?? + Name: name, + Payload: strings.ReplaceAll(e.String(), "\n", ""), + }, + } + } + + if output.NextToken == nil { + break; + } + filterOptions.NextToken = output.NextToken + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/datadog.go b/backend/services/integrations/integration/datadog.go new file mode 100644 index 000000000..eb7b5daee --- /dev/null +++ b/backend/services/integrations/integration/datadog.go @@ -0,0 +1,132 @@ +package integration + +import ( + "fmt" + "net/http" + "encoding/json" + "bytes" + "time" + "io" + "io/ioutil" + + "openreplay/backend/pkg/utime" + "openreplay/backend/pkg/messages" +) + +/* + We collect Logs. Datadog also has Events + +*/ + +type datadog struct { + ApplicationKey string //`json:"application_key"` + ApiKey string //`json:"api_key"` +} + +type datadogResponce struct { + Logs []json.RawMessage + NextLogId *string + Status string +} + +type datadogLog struct { + Content struct { + Timestamp string + Message string + Attributes struct { + Error struct { // Not sure about this + Message string + } + } + } +} + +func (d *datadog) makeRequest(nextLogId *string, fromTs uint64, toTs uint64) (*http.Request, error) { + requestURL := fmt.Sprintf( + "https://api.datadoghq.com/api/v1/logs-queries/list?api_key=%v&application_key=%v", + d.ApiKey, + d.ApplicationKey, + ) + startAt := "null" + if nextLogId != nil && *nextLogId != "" { + startAt = *nextLogId + } + // Query: status:error/info/warning? + // openReplaySessionToken instead of asayer_session_id + jsonBody := fmt.Sprintf(`{ + "limit": 1000, + "query": "status:error openReplaySessionToken", + "sort": "asc", + "time": { + "from": %v, + "to": %v + }, + "startAt": %v + }`, fromTs, toTs, startAt) // from/to: both inclusively, both required; limit: default=10, max 1000 + req, err := http.NewRequest("POST", requestURL, bytes.NewBuffer([]byte(jsonBody))) + if err != nil { + return nil, err + } + req.Header.Add("Content-Type", "application/json") + return req, nil +} + +func (d *datadog) Request(c *client) error { + fromTs := c.getLastMessageTimestamp() + 1 // From next millisecond + toTs := uint64(utime.CurrentTimestamp()) + var nextLogId *string + for { + req, err := d.makeRequest(nextLogId, fromTs, toTs) + if err != nil { + return err + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode >= 400 { + io.Copy(ioutil.Discard, resp.Body) // Read the body to free socket + return fmt.Errorf("Datadog: server respond with the code %v", resp.StatusCode) + } + var ddResp datadogResponce + if err = json.NewDecoder(resp.Body).Decode(&ddResp); err != nil { + return err + } + // if ddResp.Status != "done"/ "ok" + for _, jsonLog := range ddResp.Logs { + var ddLog datadogLog + err = json.Unmarshal(jsonLog, &ddLog) + if err != nil { + c.errChan <- err + continue + } + token, err := GetToken(ddLog.Content.Message) // sure here? + if err != nil { + c.errChan <- err + continue + } + parsedTime, err := time.Parse(time.RFC3339, ddLog.Content.Timestamp) + if err != nil { + c.errChan <- err + continue + } + timestamp := uint64(utime.ToMilliseconds(parsedTime)) + c.setLastMessageTimestamp(timestamp) + c.evChan <- &SessionErrorEvent{ + //SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "datadog", + Timestamp: timestamp, + Name: ddLog.Content.Attributes.Error.Message, + Payload: string(jsonLog), + }, + } + } + nextLogId = ddResp.NextLogId // ensure + if nextLogId == nil { + return nil + } + } +} \ No newline at end of file diff --git a/backend/services/integrations/integration/datadog.json b/backend/services/integrations/integration/datadog.json new file mode 100644 index 000000000..3e56ef79a --- /dev/null +++ b/backend/services/integrations/integration/datadog.json @@ -0,0 +1,5872 @@ +{ + "logs": [ + { + "id": "AQAAAXBULBWLl8WpFQAAAABBWEJVTEJvaG94Z0dJRTZSZzhDMg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "11c35a1c-e900-4463-8ae0-38e4d482743f" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278890000185259810132293709862379460665586328523243520", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]97e9c5eebb5a416d809333070664b4e2" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960140171 + }, + "message": "[WARNING]\t2020-02-17T17:22:20.171Z\t11c35a1c-e900-4463-8ae0-38e4d482743f\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960140, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"8a5e3540-99b0-4ff4-9251-ed86683b8f6d\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.132.29\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:22:20.171Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBULBWgyR0eOgAAAABBWEJVTEJvaEZ1QjAyaV9RRDNfXw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278890000653575459301436795861093828617443503873458182", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]97e9c5eebb5a416d809333070664b4e2" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960140192 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:22:20.192Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBULBYg4bYWMQAAAABBWEJVTEJvZ0dpZlQ0aDRaSVhEdQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "11c35a1c-e900-4463-8ae0-38e4d482743f" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278889997085456227536537093022009335760684577030864896", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]97e9c5eebb5a416d809333070664b4e2" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960140320 + }, + "message": "[WARNING]\t2020-02-17T17:22:20.32Z\t11c35a1c-e900-4463-8ae0-38e4d482743f\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960139, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"a9fc710d-b059-4197-9ab4-cc1cf5554742\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.132.29\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:22:20.320Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMEi00bMbLgAAAABBWEJVTUV6UHI0cVhDYjhkVkk5UQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "d6833386-c6ec-4121-a0a7-75630c46d06e" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896138264668998899538142086586326585235977160556544", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]50ee0782c850412baf8669ccccbcff36" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960415412 + }, + "message": "[WARNING]\t2020-02-17T17:26:55.412Z\td6833386-c6ec-4121-a0a7-75630c46d06e\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960415, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"519aae33-3dbd-4d3d-add1-39eb2adb322b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.58.149\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:26:55.412Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMEk8yKqMtAAAAABBWEJVTUV6Tktsa3NEOXgyZmdVUQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "d6833386-c6ec-4121-a0a7-75630c46d06e" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896141297570345899702889454992321378994162079367168", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]50ee0782c850412baf8669ccccbcff36" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960415548 + }, + "message": "[WARNING]\t2020-02-17T17:26:55.548Z\td6833386-c6ec-4121-a0a7-75630c46d06e\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960415, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"6f902eb7-a029-4ea7-8ebd-d4b78c24801f\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.58.149\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:26:55.548Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMElFjNHk9gAAAABBWEJVTUlkNks4aGgtVElpdDI5VQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896141498277052686478515912613650029218075478982662", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]50ee0782c850412baf8669ccccbcff36" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960415557 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:26:55.557Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUME-zl3yDoQAAAABBWEJVTUZNeUlILU9OQUZlQ19TTA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "7b3643d0-7cdb-47e2-95d7-4b50a81b73cc" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896178205303649467884190699870991211539419286077440", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960417203 + }, + "message": "[WARNING]\t2020-02-17T17:26:57.203Z\t7b3643d0-7cdb-47e2-95d7-4b50a81b73cc\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960417, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"192bc729-f12c-4b47-a56c-1e5b55f39024\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:26:57.203Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUME_H4x4-5AAAAABBWEJVTUkxRnhjcTJuVmtlaG5uMw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896178651318553438496671709617928483581328236019718", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960417223 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:26:57.223Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMFHCgLwTewAAAABBWEJVTUZLOXhjcTJuVmtlZ21xRw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "7b3643d0-7cdb-47e2-95d7-4b50a81b73cc" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896175328507518857433805283507882367264624422486016", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960417730 + }, + "message": "[WARNING]\t2020-02-17T17:26:57.73Z\t7b3643d0-7cdb-47e2-95d7-4b50a81b73cc\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960416, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"c1270310-0a99-422f-8687-d2f38778ebf1\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:26:57.730Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMFKvqA16JgAAAABBWEJVTUZTajNRSnRDMlNoTmM1VQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "405fac3c-26c0-44ce-ac23-8b23dd3d00c9" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896195265373726343810894899563945991946747062255616", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960417967 + }, + "message": "[WARNING]\t2020-02-17T17:26:57.967Z\t405fac3c-26c0-44ce-ac23-8b23dd3d00c9\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960417, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"e7b249c7-6395-428c-89dd-d7b1974428ec\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:26:57.967Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMFNElXWtXQAAAABBWEJVTUpMQi05cEZWTHk1X0hzbA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896198565884015726343138186278237684871153284022278", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960418116 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:26:58.116Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMFakjzkgDAAAAABBWEJVTUZoRVcwSnJST1JvZ0Q2bg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "405fac3c-26c0-44ce-ac23-8b23dd3d00c9" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896198164470602152791903455511813556455727545778176", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960418980 + }, + "message": "[WARNING]\t2020-02-17T17:26:58.98Z\t405fac3c-26c0-44ce-ac23-8b23dd3d00c9\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960417, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"bcdf0537-0953-4473-863b-81953d733aec\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:26:58.980Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMGQUlXWtYQAAAABBWEJVTUpMQi05cEZWTHk1X0hzcg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "c9b5a3ab-75b0-491e-a5f0-2ef9f0269b5e" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896294570592095400675762497545401436067436529713162", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960422420 + }, + "message": "[WARNING]\t2020-02-17T17:27:02.420Z\tc9b5a3ab-75b0-491e-a5f0-2ef9f0269b5e\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960422, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"8e3d7259-9446-49e4-8179-9ec9ea65d4d4\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:02.420Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMGSWlXWtYgAAAABBWEJVTUpMQi05cEZWTHk1X0hzdA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "c9b5a3ab-75b0-491e-a5f0-2ef9f0269b5e" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896297447388226011126147755653058607706070801186827", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960422550 + }, + "message": "[WARNING]\t2020-02-17T17:27:02.550Z\tc9b5a3ab-75b0-491e-a5f0-2ef9f0269b5e\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960422, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"fceddc47-d4ea-4e06-b3df-a2a22c366318\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:02.550Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMGSalXWtaQAAAABBWEJVTUpNVy05cEZWTHk1X0lIRg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896297536591206805248640321795931698299516825108498", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960422554 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:27:02.554Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMG16lXWtbQAAAABBWEJVTUpNVy05cEZWTHk1X0lISg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "59da705c-55d2-46d7-9dda-e1b7661f73a1" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896348203884297866824417890947847155376858412613654", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960424826 + }, + "message": "[WARNING]\t2020-02-17T17:27:04.826Z\t59da705c-55d2-46d7-9dda-e1b7661f73a1\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960424, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"2aad2f43-c832-496f-83c8-cc086a06e326\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:04.826Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMG39lXWtbgAAAABBWEJVTUpNVy05cEZWTHk1X0lISw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "59da705c-55d2-46d7-9dda-e1b7661f73a1" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896351147582664072866672573662659144960577202028567", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960424957 + }, + "message": "[WARNING]\t2020-02-17T17:27:04.957Z\t59da705c-55d2-46d7-9dda-e1b7661f73a1\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960424, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"8da386d2-622c-4dc8-a133-616c152dd964\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:04.957Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMG4BlXWtdQAAAABBWEJVTUpNVy05cEZWTHk1X0lIUg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278896351214484899668458541998269813962905661719969822", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960424961 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:27:04.961Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMR6t1smdcgAAAABBWEJVTVNOZnZLemljMVVDbGJvOQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5a1b4cc6-878d-416e-8259-5a94d0e06e14" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278897359832588738811482032167694712054978577644584960", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960470189 + }, + "message": "[WARNING]\t2020-02-17T17:27:50.189Z\t5a1b4cc6-878d-416e-8259-5a94d0e06e14\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960470, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"4ea6053f-fd03-426f-a7f6-b5630bf8c9e3\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:50.189Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMR8vu6RuTgAAAABBWEJVTVNOd2NFdmRyXzFZME50Qw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5a1b4cc6-878d-416e-8259-5a94d0e06e14" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278897362753986359818993663864835055521603550992465920", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960470319 + }, + "message": "[WARNING]\t2020-02-17T17:27:50.319Z\t5a1b4cc6-878d-416e-8259-5a94d0e06e14\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960470, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"5ab5ac6b-381d-4fe5-948e-c5d6fd603cb1\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:50.319Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMR806NMarwAAAABBWEJVTVY0Wl8zT0VGeWk4bDljZw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278897362843189340613116174621582694999250842122452998", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960470324 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:27:50.324Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMSN16NMaswAAAABBWEJVTVY0Wl8zT0VGeWk4bDljbg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "3fe27da6-f95c-4c60-9970-178c61bc1487" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278897387151001607011495398895515612185964883641106442", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960471413 + }, + "message": "[WARNING]\t2020-02-17T17:27:51.413Z\t3fe27da6-f95c-4c60-9970-178c61bc1487\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960471, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"f02c730c-39da-4a82-9770-a17f663fc67c\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:51.413Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMSP16NMatAAAAABBWEJVTVY0YV8zT0VGeWk4bDljbw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "3fe27da6-f95c-4c60-9970-178c61bc1487" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278897389983196247224884537870551832812306794900619275", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960471541 + }, + "message": "[WARNING]\t2020-02-17T17:27:51.541Z\t3fe27da6-f95c-4c60-9970-178c61bc1487\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960471, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"f5587aed-55b0-40b9-8072-f9c426b1e517\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:27:51.541Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUMSP56NMauwAAAABBWEJVTVY1d18zT0VGeWk4bDk3Uw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278897390072399228019007030436694705902900240924540946", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960471545 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:27:51.545Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNCLuyM-cUAAAAABBWEJVTkNWRUlILU9OQUZlVTZMVA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5487bd3e-cf82-4b04-b8f0-5cce5c995ce4" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278901768623012252720085483352034441644836427771936768", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960667886 + }, + "message": "[WARNING]\t2020-02-17T17:31:07.886Z\t5487bd3e-cf82-4b04-b8f0-5cce5c995ce4\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960667, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"d8f4cf02-c9be-42dc-8f35-69655f9b93c9\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:07.886Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNCNypWJ9ZgAAAABBWEJVTkdPQUlILU9OQUZlV2s0Yg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278901771566710618926127756383769161423429835543281670", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960668018 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:31:08.018Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNCPs22ufcQAAAABBWEJVTkNWVTItXy1jcjItRkpBZg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5487bd3e-cf82-4b04-b8f0-5cce5c995ce4" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278901771477507638132005245624667790713457829453168640", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960668140 + }, + "message": "[WARNING]\t2020-02-17T17:31:08.14Z\t5487bd3e-cf82-4b04-b8f0-5cce5c995ce4\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960667, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"57358b83-61d4-4af0-a7e8-48554fde1739\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:08.140Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNCcjpWJ9agAAAABBWEJVTkdPQUlILU9OQUZlV2s0Zg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "6e18df97-ea8a-4864-b9f0-6c3bec495027" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278901792640914831537566625135022929076131458694774794", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960668963 + }, + "message": "[WARNING]\t2020-02-17T17:31:08.963Z\t6e18df97-ea8a-4864-b9f0-6c3bec495027\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960668, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"df286414-5824-41d6-98b0-7b5a215e95ce\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:08.963Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNCeopWJ9cgAAAABBWEJVTkdQV0lILU9OQUZlV2wzNg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278901795606913942942139502959273459338363538990170130", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960669096 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:31:09.096Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNCrgpWJ9awAAAABBWEJVTkdPQUlILU9OQUZlV2s0Zw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "6e18df97-ea8a-4864-b9f0-6c3bec495027" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278901795517710962148017010393130586247770092966248459", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960669920 + }, + "message": "[WARNING]\t2020-02-17T17:31:09.92Z\t6e18df97-ea8a-4864-b9f0-6c3bec495027\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960668, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"61e2e561-dd10-4ba4-b292-71b7b7c8b0ea\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:09.920Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGR23CN23wAAAABBWEJVTkdmVm94Z0dJRTZSRHM4eA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a6647a21-5ebf-43a9-985b-55819e8c3370" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902142740313703269819326043482739780083425881489408", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960684662 + }, + "message": "[WARNING]\t2020-02-17T17:31:24.662Z\ta6647a21-5ebf-43a9-985b-55819e8c3370\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960684, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"7ce61a98-4cd0-4540-adc1-5f9556055e93\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:24.662Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGT34KuMbAAAAABBWEJVTkdmWjdyclJnT2RTakk1Mg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a6647a21-5ebf-43a9-985b-55819e8c3370" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902145617109833880269711451561022249350734399537152", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960684791 + }, + "message": "[WARNING]\t2020-02-17T17:31:24.791Z\ta6647a21-5ebf-43a9-985b-55819e8c3370\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960684, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"877d3030-4b28-4278-bacc-5df530d6c279\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:24.791Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGT6n4mgdgAAAABBWEJVTktKZlVreVN1OHh3aEdvRg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902145684012069475861599062201880745813945823789062", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960684794 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:31:24.794Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGi2n4mgegAAAABBWEJVTktKZlVreVN1OHh3aEdvSg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "70e7665e-3e8a-4100-8d7b-c2cfd9dfc098" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902167025825224469667945511884267670295907047047178", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960685750 + }, + "message": "[WARNING]\t2020-02-17T17:31:25.750Z\t70e7665e-3e8a-4100-8d7b-c2cfd9dfc098\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960685, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"474a088a-22d6-4f0e-ac71-4421e4be8030\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:25.750Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGk5n4mgewAAAABBWEJVTktKZlVreVN1OHh3aEdvSw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "70e7665e-3e8a-4100-8d7b-c2cfd9dfc098" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902169947222845477179577053063361387231264330481675", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960685881 + }, + "message": "[WARNING]\t2020-02-17T17:31:25.881Z\t70e7665e-3e8a-4100-8d7b-c2cfd9dfc098\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960685, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"3922c242-9f51-4cdc-9066-64b856bd9d0b\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:25.881Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGk9n4mgggAAAABBWEJVTktLWlVreVN1OHh3aEczLQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902170014125081072771446477670516205176348848422930", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960685885 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:31:25.885Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGw-n4mghgAAAABBWEJVTktLWlVreVN1OHh3aEc0Qw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "2c0fac29-89c4-414d-96e2-5a999c55c526" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902187163398138742820642318637867871766346947362838", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960686654 + }, + "message": "[WARNING]\t2020-02-17T17:31:26.654Z\t2c0fac29-89c4-414d-96e2-5a999c55c526\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960686, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"f3f4c8f0-9a78-4060-9577-3b1962edcbc5\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:26.654Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGy_n4mghwAAAABBWEJVTktLWlVreVN1OHh3aEc0RA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "2c0fac29-89c4-414d-96e2-5a999c55c526" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902190040194269353271027576745525043404981218836503", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960686783 + }, + "message": "[WARNING]\t2020-02-17T17:31:26.783Z\t2c0fac29-89c4-414d-96e2-5a999c55c526\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960686, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"4a5723e0-e956-462d-9738-4062263b44d6\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:26.783Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNGzCn4mgjgAAAABBWEJVTktLblVreVN1OHh3aEc1bg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902190107096504948862897001352679861350065736777758", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960686786 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:31:26.786Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNHB1n4mgkgAAAABBWEJVTktLb1VreVN1OHh3aEc1cg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "e171a658-14fa-41f2-80aa-02bc4705329d" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902211225902207957363012035677884059348411900231714", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960687733 + }, + "message": "[WARNING]\t2020-02-17T17:31:27.733Z\te171a658-14fa-41f2-80aa-02bc4705329d\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960687, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"48b77e84-700a-4dee-8639-cd4afe7dd00b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:27.733Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNHD1n4mgkwAAAABBWEJVTktLb1VreVN1OHh3aEc1cw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "e171a658-14fa-41f2-80aa-02bc4705329d" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902214080397593369282774152249822958338684665724963", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960687861 + }, + "message": "[WARNING]\t2020-02-17T17:31:27.861Z\te171a658-14fa-41f2-80aa-02bc4705329d\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960687, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"6db5919b-6228-416d-a2ce-75b51595528a\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:31:27.861Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNHD5n4mgmgAAAABBWEJVTktMeFVreVN1OHh3aEhKRA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278902214169600574163405266718392696048932130689646634", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960687865 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:31:27.865Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQlmlaiVYAAAAABBWEJVTlF3MS05cEZWTHk1VUZMNg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "67874f03-e0b1-4e9f-b628-33602f4ef355" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903084389279711225381528430218830756520936086700032", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960726886 + }, + "message": "[WARNING]\t2020-02-17T17:32:06.886Z\t67874f03-e0b1-4e9f-b628-33602f4ef355\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960726, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"fd33c89d-08b8-4ad7-89f2-9a270e2f10d6\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:06.886Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQnrw0TDugAAAABBWEJVTlVvdlBQSlBKbnd3SW9CUw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903087332978077431423801459328149603679600775987206", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727019 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:07.019Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQpNj67eEAAAAABBWEJVTlEzYzl0anJaNlJRY1BjYg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "6bec467f-525e-4fd3-bb19-193369e4f2a0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903089518451106887424851263681094016809700641669120", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727117 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.117Z\t6bec467f-525e-4fd3-bb19-193369e4f2a0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960726, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"35c84447-de1c-44f2-938c-d2d0246f4a22\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.117Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQpuz-5FhAAAAABBWEJVTlF3NXhjcTJuVmtlMTl1Zw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "67874f03-e0b1-4e9f-b628-33602f4ef355" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903087266075841835831913842593478981722380101943296", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727150 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.15Z\t67874f03-e0b1-4e9f-b628-33602f4ef355\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960726, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"d9769f59-3232-4548-8c27-db867307039e\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.150Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQrOvqYylwAAAABBWEJVTlEzZ0dpZlQ0aDRacU82Qg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "6bec467f-525e-4fd3-bb19-193369e4f2a0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903092395247237497875236676678577550179676838428672", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727246 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.246Z\t6bec467f-525e-4fd3-bb19-193369e4f2a0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"b815987f-fa94-44e8-9647-ebae1791414e\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.246Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQrS3yLW_wAAAABBWEJVTlVoaW94Z0dJRTZSSURqSQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903092484450218291997747421221452898216837860098054", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727250 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:07.250Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQrrrM7NJwAAAABBWEJVTlFfQzdyclJnT2RTbElyRQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "bb2b579b-4f4d-484e-b08e-29e17b41b389" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903093041968848255263307815966294289455569020846080", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]50ee0782c850412baf8669ccccbcff36" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727275 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.275Z\tbb2b579b-4f4d-484e-b08e-29e17b41b389\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"fc6da1be-ee18-4f1b-b9e9-4bc06e3bf91a\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.58.149\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.275Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQsuw0TDvgAAAABBWEJVTlVvdlBQSlBKbnd3SW9CVw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5c5749e2-8959-4bab-8d97-cd4f1d3c12fb" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903094536118776556815076175365151669100367207661578", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727342 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.342Z\t5c5749e2-8959-4bab-8d97-cd4f1d3c12fb\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"32ac8078-961e-4b95-889f-61ba1b2d84e3\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.342Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQtx9w7ygwAAAABBWEJVTlFfRXJVUGwtQmU5UUR3Nw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "bb2b579b-4f4d-484e-b08e-29e17b41b389" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903096030268704858366808944078066657618964372586496", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]50ee0782c850412baf8669ccccbcff36" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727409 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.409Z\tbb2b579b-4f4d-484e-b08e-29e17b41b389\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"6e93e834-ae54-470f-9245-6abb9df4b093\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.58.149\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.409Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQt1vb2wLgAAAABBWEJVTlVwWUMwTmF2TjVhbmdYbw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903096119471685652489319685297484637549112435671046", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]50ee0782c850412baf8669ccccbcff36" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727413 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:07.413Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQvAw0TDvwAAAABBWEJVTlVvdlBQSlBKbnd3SW9CWA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5c5749e2-8959-4bab-8d97-cd4f1d3c12fb" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903097814328320740816677981115737748409508586782731", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727488 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.488Z\t5c5749e2-8959-4bab-8d97-cd4f1d3c12fb\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"ded8e07f-5514-45e0-a892-e2e18681fb85\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.488Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQvC3yLXAwAAAABBWEJVTlVoaW94Z0dJRTZSSURqTQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "3d7ada38-cde5-46ba-866a-dbbea6393f46" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903097836629065939347301389793838333823599295397898", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727490 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.490Z\t3d7ada38-cde5-46ba-866a-dbbea6393f46\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"28e24935-52af-4938-9ac5-7e1a7a9a4fbc\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.490Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQvEw0TDxgAAAABBWEJVTlVwMlBQSlBKbnd3SW9PTQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903097881230556336408547405722892566354593104723986", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727492 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:07.492Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQxF3yLXBAAAAABBWEJVTlVoaW94Z0dJRTZSSURqTg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "3d7ada38-cde5-46ba-866a-dbbea6393f46" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903100758026686946858932930972932050758956578832395", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727621 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.621Z\t3d7ada38-cde5-46ba-866a-dbbea6393f46\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"b9f214a1-77d8-4c81-9742-29600cb67393\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.621Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQxJ3yLXCwAAAABBWEJVTlVpM294Z0dJRTZSSUVMcA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903100847229667740981425497115805141352402602754066", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727625 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:07.625Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQyvw0TDygAAAABBWEJVTlVwMlBQSlBKbnd3SW9PUQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "9f65476e-e445-4728-aa6d-e0ab88fcd3d9" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903103121905677991104985666616686638719547010121750", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727727 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.727Z\t9f65476e-e445-4728-aa6d-e0ab88fcd3d9\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"7b89fb30-6309-4311-9240-4d6bcc932407\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.727Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQ0uw0TDywAAAABBWEJVTlVwMlBQSlBKbnd3SW9PUg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "9f65476e-e445-4728-aa6d-e0ab88fcd3d9" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903105954100318204494124641652907265061458269634583", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727854 + }, + "message": "[WARNING]\t2020-02-17T17:32:07.854Z\t9f65476e-e445-4728-aa6d-e0ab88fcd3d9\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960727, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"8a163336-8ef9-4f01-a743-cc6a47727384\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:07.854Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNQ0ww0TD0gAAAABBWEJVTlVxRVBQSlBKbnd3SW9ScA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903105998701808601555370924724343810358181281595422", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960727856 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:07.856Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRDAw0TD1gAAAABBWEJVTlVxRVBQSlBKbnd3SW9SdA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "ef1fa9b5-f63b-4fc1-a398-3f34b34efdfa" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903126336981429661483676005299408465663874735734818", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960728768 + }, + "message": "[WARNING]\t2020-02-17T17:32:08.768Z\tef1fa9b5-f63b-4fc1-a398-3f34b34efdfa\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960728, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"ab727ab3-1d02-43da-80e1-f1bf9926f1fd\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:08.768Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRE_w0TD1wAAAABBWEJVTlVxRVBQSlBKbnd3SW9SdQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "ef1fa9b5-f63b-4fc1-a398-3f34b34efdfa" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903129169176069874872814980335629092005785995247651", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960728895 + }, + "message": "[WARNING]\t2020-02-17T17:32:08.895Z\tef1fa9b5-f63b-4fc1-a398-3f34b34efdfa\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960728, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"23c7c474-b128-4463-9f36-55d03b28ea27\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:08.895Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRFDw0TD3gAAAABBWEJVTlVyTVBQSlBKbnd3SW9neQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903129258379050668995307546478502182599232019169322", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960728899 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:08.899Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRRK9Ott3gAAAABBWEJVTlJnakZZNkduTFVZdldBVw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "f0a94b5c-0262-4381-8698-0ccf71c3b9d8" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903146541456579530228227261681532271304742861012992", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960729674 + }, + "message": "[WARNING]\t2020-02-17T17:32:09.674Z\tf0a94b5c-0262-4381-8698-0ccf71c3b9d8\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960729, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"67e13aa1-27c7-4059-b9bc-97727b2498ea\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:09.674Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRTM7G9g3wAAAABBWEJVTlJnM3IwZ29yZHV3TlA0Zg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "f0a94b5c-0262-4381-8698-0ccf71c3b9d8" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903149440553455339209235818321002943580325726322688", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960729804 + }, + "message": "[WARNING]\t2020-02-17T17:32:09.804Z\tf0a94b5c-0262-4381-8698-0ccf71c3b9d8\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960729, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"6a3af199-ec6a-4042-a08f-e1ab7aa83b39\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:09.804Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRTewDstQQAAAABBWEJVTlZMTnZLemljMVVDMDh1YQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903149841966868912760470543678724895583585183596550", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960729822 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:09.822Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRduwDstRQAAAABBWEJVTlZMTnZLemljMVVDMDh1Ng", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "25d80dda-deff-4cef-b008-ef45036e64fa" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903164471255719148849251391109911752908733106749450", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960730478 + }, + "message": "[WARNING]\t2020-02-17T17:32:10.478Z\t25d80dda-deff-4cef-b008-ef45036e64fa\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960730, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"beb8e286-6f39-4c64-814d-23df622c0803\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": null}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:10.478Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRf2wDstRgAAAABBWEJVTlZMTnZLemljMVVDMDh2Qg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "25d80dda-deff-4cef-b008-ef45036e64fa" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903167504157066149013998639967596833085897920086027", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960730614 + }, + "message": "[WARNING]\t2020-02-17T17:32:10.614Z\t25d80dda-deff-4cef-b008-ef45036e64fa\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960730, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"85899303-158a-42ae-a345-1ab4e32212d7\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:32:10.614Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUNRf6wDstTQAAAABBWEJVTlZNanZLemljMVVDMDg0cg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278903167593360046943136491206110469923679343944007698", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960730618 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:32:10.618Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOJMfxGqrEQAAAABBWEJVT0piSUZ1QjAyaV9Rei1aYg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "eef068a9-69e0-4353-b799-25f83fb7cae0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908255129264423329785897774472633258025408685998080", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960958751 + }, + "message": "[WARNING]\t2020-02-17T17:35:58.751Z\teef068a9-69e0-4353-b799-25f83fb7cae0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960958, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"fe4e06c1-0f82-48d1-8bc0-39b27c47301c\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:35:58.751Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOJOggq4iGAAAAABBWEJVT0piYWVJNUlYNjZoUzJSZA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "eef068a9-69e0-4353-b799-25f83fb7cae0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908258006060553940236283188155145220915591948730368", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960958880 + }, + "message": "[WARNING]\t2020-02-17T17:35:58.880Z\teef068a9-69e0-4353-b799-25f83fb7cae0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960958, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"eb77fcbd-c605-4d14-b109-08efed46810d\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:35:58.880Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOJOkhBrL7gAAAABBWEJVT05HUEtsa3NEOXgyLUZfdA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908258095263534734358793953323969076966814257446918", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960958884 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:35:58.884Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOJ1GhBrL8gAAAABBWEJVT05HUUtsa3NEOXgyLUZfeA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a505c6d0-04e8-4408-86cf-479cb338c8b7" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908313088901194310875460980405229427826288005152778", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960961350 + }, + "message": "[WARNING]\t2020-02-17T17:36:01.350Z\ta505c6d0-04e8-4408-86cf-479cb338c8b7\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960961, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"1a7ec240-5523-4a27-a943-2aa113337c5b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:01.350Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOJ3ThBrL8wAAAABBWEJVT05HUUtsa3NEOXgyLUZfeQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a505c6d0-04e8-4408-86cf-479cb338c8b7" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908316233306267303693323936941505871245260348391435", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960961491 + }, + "message": "[WARNING]\t2020-02-17T17:36:01.491Z\ta505c6d0-04e8-4408-86cf-479cb338c8b7\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960961, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"6bf0ebc9-7e41-4156-b67c-c2c1dd4889ec\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:01.491Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOJ3XhBrL-gAAAABBWEJVT05Ibktsa3NEOXgyLUdKNg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908316322509248097815816503084378961838706372313106", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960961495 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:01.495Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKDshBrL_gAAAABBWEJVT05Ibktsa3NEOXgyLUdKLQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "1672c893-9b37-4117-8d8e-8bc3d9178fc4" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908333917797209738477475174766096081395934590861334", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960962284 + }, + "message": "[WARNING]\t2020-02-17T17:36:02.284Z\t1672c893-9b37-4117-8d8e-8bc3d9178fc4\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960962, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"51f5ad37-22d9-4721-bfbe-60fe9e3a2a71\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:02.284Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKFuhBrL_wAAAABBWEJVT05Ibktsa3NEOXgyLUdKXw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "1672c893-9b37-4117-8d8e-8bc3d9178fc4" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908336839194830745989106715945189798331291874295831", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960962414 + }, + "message": "[WARNING]\t2020-02-17T17:36:02.414Z\t1672c893-9b37-4117-8d8e-8bc3d9178fc4\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960962, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"0979d67b-caba-4b28-a2c3-6436bef953ba\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:02.414Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKFyhBrMBgAAAABBWEJVT05Ibktsa3NEOXgyLUdLRw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908336906097066341580976140552344616276376392237086", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960962418 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:02.418Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKQmhBrMCgAAAABBWEJVT05Ibktsa3NEOXgyLUdLSw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a4bf78e3-56e7-4e7c-a60b-2f73fb3e77fe" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908352338212743724772190083269389288942538530684962", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960963110 + }, + "message": "[WARNING]\t2020-02-17T17:36:03.110Z\ta4bf78e3-56e7-4e7c-a60b-2f73fb3e77fe\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960962, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"dfdd4aa5-3be8-4209-bcd4-8a0bcd197039\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:03.110Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKS_hBrMCwAAAABBWEJVT05Ibktsa3NEOXgyLUdLTA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a4bf78e3-56e7-4e7c-a60b-2f73fb3e77fe" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908355750226759099957530738234285004141848945688611", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960963263 + }, + "message": "[WARNING]\t2020-02-17T17:36:03.263Z\ta4bf78e3-56e7-4e7c-a60b-2f73fb3e77fe\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960963, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"e05fbc83-3093-4edc-bda9-106e0b697ee4\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:03.263Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKTUhBrMEgAAAABBWEJVT05JOEtsa3NEOXgyLUdVZg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908356218542408269100616710484368729757440571277354", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960963284 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:03.284Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKkFhBrMFgAAAABBWEJVT05JOEtsa3NEOXgyLUdVag", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "30a51b11-730d-4d57-aaf6-142de8e731cf" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908380147242006292459247578310075281449336488263726", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960964357 + }, + "message": "[WARNING]\t2020-02-17T17:36:04.357Z\t30a51b11-730d-4d57-aaf6-142de8e731cf\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960964, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"da95be65-29c8-49ac-8b76-0318f89ccd29\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:04.357Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKmIhBrMFwAAAABBWEJVT05JOEtsa3NEOXgyLUdVaw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "30a51b11-730d-4d57-aaf6-142de8e731cf" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908383068639627299970879119489168998384693771698223", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960964488 + }, + "message": "[WARNING]\t2020-02-17T17:36:04.488Z\t30a51b11-730d-4d57-aaf6-142de8e731cf\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960964, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"8f733e32-1a96-47b4-ab78-0941e55c97ed\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:04.488Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOKmMhBrMHgAAAABBWEJVT05JOUtsa3NEOXgyLUdVcg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908383157842608094093371685632042088978139795619894", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960964492 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:04.492Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOK0EhBrMIgAAAABBWEJVT05JOUtsa3NEOXgyLUdVdg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "2785e5fc-7425-4a13-802b-200d8a1f1ed0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908402960904344389286721369349868200723157106229306", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960965380 + }, + "message": "[WARNING]\t2020-02-17T17:36:05.380Z\t2785e5fc-7425-4a13-802b-200d8a1f1ed0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960965, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"cf85daf6-5583-4ca2-b38e-310a7783bd17\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:05.380Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOK2YhBrMIwAAAABBWEJVT05JOUtsa3NEOXgyLUdVdw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "2785e5fc-7425-4a13-802b-200d8a1f1ed0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908406283715378970349569458171890825329021497311291", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960965528 + }, + "message": "[WARNING]\t2020-02-17T17:36:05.528Z\t2785e5fc-7425-4a13-802b-200d8a1f1ed0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960965, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"c3fb7c50-984b-4673-8c8b-bd112ce658e4\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:05.528Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOK2chBrMKgAAAABBWEJVT05JOUtsa3NEOXgyLUdVMw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908406350617614565941438882779045643274106015252546", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960965532 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:05.532Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOK_3hBrMLgAAAABBWEJVT05JOUtsa3NEOXgyLUdVNw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "2476dc61-55f5-42db-92ce-3f6298287e04" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908419797966969279907193228817164050236094121443398", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960966135 + }, + "message": "[WARNING]\t2020-02-17T17:36:06.135Z\t2476dc61-55f5-42db-92ce-3f6298287e04\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960966, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"40c2191b-252c-4ee9-a457-d000d751cd4b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:06.135Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLCDhBrMLwAAAABBWEJVT05JOUtsa3NEOXgyLUdWQQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "2476dc61-55f5-42db-92ce-3f6298287e04" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908422920071297074194433043817722221006704958701639", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960966275 + }, + "message": "[WARNING]\t2020-02-17T17:36:06.275Z\t2476dc61-55f5-42db-92ce-3f6298287e04\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960966, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"8b7bed24-1d14-45ac-a7dc-e5be445bfb11\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:06.275Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLCHhBrMNgAAAABBWEJVT05JOUtsa3NEOXgyLUdWSA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908423009274277868316925609960595311600150982623310", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960966279 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:06.279Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLLIhBrMOgAAAABBWEJVT05JOUtsa3NEOXgyLUdWTA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "ef3338af-7d50-4b8b-bcb9-3466c90f88ac" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908435899105002619017101417605756902353101439303762", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960966856 + }, + "message": "[WARNING]\t2020-02-17T17:36:06.856Z\tef3338af-7d50-4b8b-bcb9-3466c90f88ac\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960966, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"0574a9b2-ecf0-4cbf-8760-cc68a626f91c\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:06.856Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLNOhBrMOwAAAABBWEJVT05JOUtsa3NEOXgyLUdWTQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "ef3338af-7d50-4b8b-bcb9-3466c90f88ac" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908438865104114023589979241856287164585181734699091", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960966990 + }, + "message": "[WARNING]\t2020-02-17T17:36:06.990Z\tef3338af-7d50-4b8b-bcb9-3466c90f88ac\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960966, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"4a578477-9770-4860-9c69-046edf6774eb\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:06.990Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLNRhBrMQgAAAABBWEJVT05JLUtsa3NEOXgyLUdWVA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908438932006349619181848666463441982530266252640346", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960966993 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:06.993Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLYAhBrMRgAAAABBWEJVT05LVEtsa3NEOXgyLUd0aQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "b22f7fc3-afd5-4998-b9fd-debf2c1d6426" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908454252618301009719946901501895291954620861186142", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960967680 + }, + "message": "[WARNING]\t2020-02-17T17:36:07.680Z\tb22f7fc3-afd5-4998-b9fd-debf2c1d6426\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960967, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"23ec9a21-2284-4d00-ad18-e79d344f95a1\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:07.680Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLaEhBrMRwAAAABBWEJVT05LVEtsa3NEOXgyLUd0ag", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "b22f7fc3-afd5-4998-b9fd-debf2c1d6426" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908457218617412414292824725752425554186701156581471", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960967812 + }, + "message": "[WARNING]\t2020-02-17T17:36:07.812Z\tb22f7fc3-afd5-4998-b9fd-debf2c1d6426\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960967, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"4b3ed9dc-bf83-4ac9-8fa6-2a7ed077ca68\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:07.812Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLaIhBrMTgAAAABBWEJVT05LVEtsa3NEOXgyLUd0cQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908457285519648009884694150359580372131785674522726", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960967816 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:07.816Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLiihBrMUgAAAABBWEJVT05LVEtsa3NEOXgyLUd0dQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "f9ec4c54-1196-4e94-b197-39c83356dfe2" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908469283320564819359944296576011056950275891986538", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968354 + }, + "message": "[WARNING]\t2020-02-17T17:36:08.354Z\tf9ec4c54-1196-4e94-b197-39c83356dfe2\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"4e297723-bede-48a5-97ae-3d196ec1e078\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:08.354Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLknhBrMUwAAAABBWEJVT05LVEtsa3NEOXgyLUd0dg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "f9ec4c54-1196-4e94-b197-39c83356dfe2" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908472249319676223932822120826541319182356187381867", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968487 + }, + "message": "[WARNING]\t2020-02-17T17:36:08.487Z\tf9ec4c54-1196-4e94-b197-39c83356dfe2\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"aebdd4d5-b62c-4378-bf92-510918e1d342\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:08.487Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLkqhBrMWgAAAABBWEJVT05LVEtsa3NEOXgyLUd0Mg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908472316221911819524691545433696137127440705323122", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968490 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:08.490Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLoS_FFALgAAAABBWEJVT0wweVBXVmVPMHZHM1pWWQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "231a6ce9-4430-43b8-9948-2451a2787e0c" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908477489994797878629254081216553800615680367722496", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968722 + }, + "message": "[WARNING]\t2020-02-17T17:36:08.722Z\t231a6ce9-4430-43b8-9948-2451a2787e0c\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"805b963d-108c-47b8-a59b-389de543d374\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:08.722Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLrE21bwqgAAAABBWEJVT0wwNmVKSDRac044OGhTZA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "231a6ce9-4430-43b8-9948-2451a2787e0c" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908481481828188415610796632575563726304965251235840", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968900 + }, + "message": "[WARNING]\t2020-02-17T17:36:08.900Z\t231a6ce9-4430-43b8-9948-2451a2787e0c\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"217daee4-17a2-408c-ade5-0b35a40170a4\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:08.900Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLrJyu3ABgAAAABBWEJVT1BmY3IwZ29yZHV3YXBmWA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908481571031169209733307518347467946127302039240710", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968905 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:08.905Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLrmhBrMXgAAAABBWEJVT05LVEtsa3NEOXgyLUd0Ng", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a211efb2-2b69-4205-a70b-8d2bdb9b79f1" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908482217752779967121366387292609192999949360627830", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960968934 + }, + "message": "[WARNING]\t2020-02-17T17:36:08.934Z\ta211efb2-2b69-4205-a70b-8d2bdb9b79f1\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"267070d3-3523-4b12-91e6-69c532b3de1b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:08.934Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLuZhBrMXwAAAABBWEJVT05LVEtsa3NEOXgyLUd0Nw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a211efb2-2b69-4205-a70b-8d2bdb9b79f1" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908486209586170504102908722186179997056658931122295", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969113 + }, + "message": "[WARNING]\t2020-02-17T17:36:09.113Z\ta211efb2-2b69-4205-a70b-8d2bdb9b79f1\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"33cdbdf7-3e71-48bf-95b1-6a868482d55e\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.47.125\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:09.113Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLudhBrMZgAAAABBWEJVT05LVEtsa3NEOXgyLUd1Qw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908486298789151298225401288329053087650104955043966", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]047e2fde7d1d485a8bd1c83ab1b9d092" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969117 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:09.117Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLu6viMsdAAAAABBWEJVT0w5U2JMczZ2SHB2TnZBQg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "aa3ee2be-6c6e-467e-9648-bbd2b4d80044" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908486967811507254144089748626025618352092354969600", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969146 + }, + "message": "[WARNING]\t2020-02-17T17:36:09.146Z\taa3ee2be-6c6e-467e-9648-bbd2b4d80044\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960968, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"b26b1485-00a0-4b1f-aa7b-5d0ac63f0e80\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:09.146Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLxgtra0xQAAAABBWEJVT0w5TmxTUEpvVEJ6S1pRTQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "aa3ee2be-6c6e-467e-9648-bbd2b4d80044" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908490669735210210227531444074079999332572630155264", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969312 + }, + "message": "[WARNING]\t2020-02-17T17:36:09.312Z\taa3ee2be-6c6e-467e-9648-bbd2b4d80044\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960969, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"0aa2a936-5389-4b68-b476-3a64add59653\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.156.181\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:09.312Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLxoyu3ACgAAAABBWEJVT1BmY3IwZ29yZHV3YXBmYg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "7c15c225-32d9-4211-8e93-395149064a60" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908490825840426599941911255670551095197327021113354", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969320 + }, + "message": "[WARNING]\t2020-02-17T17:36:09.320Z\t7c15c225-32d9-4211-8e93-395149064a60\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960969, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"d46ca0ad-c4fb-4e16-989d-95d2fb730cd9\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:09.320Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLxvlHYv2AAAAABBWEJVT1BvV0w0VXlVekd5TVRHQQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908490981945642989656273598297963671299138546499590", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]ffe40bac5a41429ab760ae80fcb0d598" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969327 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:09.327Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOLz9yu3ACwAAAABBWEJVT1BmY3IwZ29yZHV3YXBmYw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "7c15c225-32d9-4211-8e93-395149064a60" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908494148651461181004759344492573719803191412195339", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969469 + }, + "message": "[WARNING]\t2020-02-17T17:36:09.469Z\t7c15c225-32d9-4211-8e93-395149064a60\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960969, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"05e8d7a3-f16d-4d37-803e-b92f9f6a2155\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:09.469Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOL0Byu3AEgAAAABBWEJVT1BneXIwZ29yZHV3YXB3Rg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908494237854441975127251910635446810396637436117010", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960969473 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:09.473Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOMF-yu3AFgAAAABBWEJVT1BneXIwZ29yZHV3YXB3Sg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "06b22657-b44f-46ba-a937-e86a359f7217" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908519861410675086813241535175742083364007807614998", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960970622 + }, + "message": "[WARNING]\t2020-02-17T17:36:10.622Z\t06b22657-b44f-46ba-a937-e86a359f7217\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960970, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"3bde7812-be3e-443e-ad02-706565984ebc\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:10.622Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOMIiyu3AFwAAAABBWEJVT1BneXIwZ29yZHV3YXB3Sw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "06b22657-b44f-46ba-a937-e86a359f7217" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908523518732887645835436747033538797695294788403223", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960970786 + }, + "message": "[WARNING]\t2020-02-17T17:36:10.786Z\t06b22657-b44f-46ba-a937-e86a359f7217\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960970, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"aa6559a3-671c-4b85-9311-7d44fff947d2\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:10.786Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOMIlyu3AHgAAAABBWEJVT1BneXIwZ29yZHV3YXB3Ug", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908523585635123241427306171640693615640379306344478", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960970789 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:10.789Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOMUpyu3AIgAAAABBWEJVT1BneXIwZ29yZHV3YXB3Vg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "d0eb19c7-9814-4939-b13f-54352e571c08" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908540801810416507068371437215200100175461923225634", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960971561 + }, + "message": "[WARNING]\t2020-02-17T17:36:11.561Z\td0eb19c7-9814-4939-b13f-54352e571c08\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960971, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"22aad693-3e5d-4d6f-b217-24263e260885\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:11.561Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOMXLyu3AIwAAAABBWEJVT1BneXIwZ29yZHV3YXB3Vw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "d0eb19c7-9814-4939-b13f-54352e571c08" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908544436831883867559943507537278541858387398033443", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960971723 + }, + "message": "[WARNING]\t2020-02-17T17:36:11.723Z\td0eb19c7-9814-4939-b13f-54352e571c08\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960971, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"975ffcf3-7338-4f9a-b16e-9b71e12de722\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:11.723Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOMXPyu3AKgAAAABBWEJVT1BpSXIwZ29yZHV3YXA0cw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908544503734119463151812932144433359803471915974698", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960971727 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:11.727Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORKnlTMrRgAAAABBWEJVT1JjR1BQSlBKbnd3VnRUWQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "6f509c34-f3c6-4dc1-8586-c256d6cef774" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908983203993664957570262125571774491122468805345280", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960991399 + }, + "message": "[WARNING]\t2020-02-17T17:36:31.399Z\t6f509c34-f3c6-4dc1-8586-c256d6cef774\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960991, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"2b3d4ff2-a01e-46cd-a16c-3c7d0b359a6a\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:31.399Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORM60Yur1QAAAABBWEJVT1ZJczR4YWdPZVNQQmJ1Uw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "6f509c34-f3c6-4dc1-8586-c256d6cef774" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908986482203209141571882117243534990773199914860599", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960991546 + }, + "message": "[WARNING]\t2020-02-17T17:36:31.546Z\t6f509c34-f3c6-4dc1-8586-c256d6cef774\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960991, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"9ea64451-e4ef-482d-b671-b9a1dcf87d31\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:31.546Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORM-0Yur3AAAAABBWEJVT1ZJczR4YWdPZVNQQmJ1Wg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278908986571406189935694374683386408081366645938782270", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960991550 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:31.550Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORcL0Yur4AAAAABBWEJVT1ZJczR4YWdPZVNQQmJ1ZA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "f601dda1-7089-4d37-801a-9599eb47b3a6" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909008270031268105990691397640287368222391257727042", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960992523 + }, + "message": "[WARNING]\t2020-02-17T17:36:32.523Z\tf601dda1-7089-4d37-801a-9599eb47b3a6\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960992, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"b3c84741-3ff6-40e0-83eb-37872275c7e1\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:32.523Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOReL0Yur4QAAAABBWEJVT1ZJczR4YWdPZVNQQmJ1bA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "f601dda1-7089-4d37-801a-9599eb47b3a6" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909011124526653517910453514212226267212664023220291", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960992651 + }, + "message": "[WARNING]\t2020-02-17T17:36:32.651Z\tf601dda1-7089-4d37-801a-9599eb47b3a6\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960992, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"0872684c-a6a3-498f-8ba3-a4a7fcbe6648\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:32.651Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOReO0Yur6AAAAABBWEJVT1ZJczR4YWdPZVNQQmJ2RQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909011191428889113502322938819381085157748541161546", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960992654 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:32.654Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORvR0Yur7AAAAABBWEJVT1ZJczR4YWdPZVNQQmJ2SQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "4b0ccb2e-bba2-4de3-b804-5c8d3ed35cf0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909035521541900710412170354288016544520151565795406", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960993745 + }, + "message": "[WARNING]\t2020-02-17T17:36:33.745Z\t4b0ccb2e-bba2-4de3-b804-5c8d3ed35cf0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960993, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"956ed261-8d2e-4ec4-960d-ccdcad5780b8\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:33.745Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORxQ0Yur7QAAAABBWEJVT1ZJczR4YWdPZVNQQmJ2Sg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "4b0ccb2e-bba2-4de3-b804-5c8d3ed35cf0" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909038353736540923801309329324237170862062825308239", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960993872 + }, + "message": "[WARNING]\t2020-02-17T17:36:33.872Z\t4b0ccb2e-bba2-4de3-b804-5c8d3ed35cf0\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960993, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"fbb003f6-2870-4063-b248-cbbebb56e25c\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:33.872Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUORxT0Yur9AAAAABBWEJVT1ZJczR4YWdPZVNQQmJ2UQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909038420638776519393178753931391988807147343249494", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960993875 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:33.875Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOR-P0Yur-AAAAABBWEJVT1ZJczR4YWdPZVNQQmJ2VQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "97e1d0bc-451b-4dc0-9e50-5dc7d4d17d1e" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909056907956546101279763087041840014298835801014362", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960994703 + }, + "message": "[WARNING]\t2020-02-17T17:36:34.703Z\t97e1d0bc-451b-4dc0-9e50-5dc7d4d17d1e\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960994, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"0160ce58-2c7b-4554-a728-6ed668e07664\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:34.703Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSAP0Yur-QAAAABBWEJVT1ZKVjR4YWdPZVNQQmJfOA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "97e1d0bc-451b-4dc0-9e50-5dc7d4d17d1e" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909059762451931513199525203613778913289108566507611", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960994831 + }, + "message": "[WARNING]\t2020-02-17T17:36:34.831Z\t97e1d0bc-451b-4dc0-9e50-5dc7d4d17d1e\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960994, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"1e0bcf94-fdbc-493f-8179-3c367aca12f9\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:34.831Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSAT0YusAAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXVA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909059829354167108791394628220933731234193084448866", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960994835 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:34.835Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSNj0YusBAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXWA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a715559f-75ef-42ca-8b17-f9281e2ba17a" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909078740386095462759818650510028937044750155841638", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960995683 + }, + "message": "[WARNING]\t2020-02-17T17:36:35.683Z\ta715559f-75ef-42ca-8b17-f9281e2ba17a\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960995, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"04aea8a8-99ac-4254-b7a5-db5fc4db3d3b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:35.683Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSPi0YusBQAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXWQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a715559f-75ef-42ca-8b17-f9281e2ba17a" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909081572580735676148957625546249563386661415354471", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960995810 + }, + "message": "[WARNING]\t2020-02-17T17:36:35.810Z\ta715559f-75ef-42ca-8b17-f9281e2ba17a\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960995, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"72367b23-c8ea-43dd-8f58-1e3b97b7030b\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:35.810Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSPq0YusDAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXZg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909081750986697264393942757831995744573553463197806", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960995818 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:35.818Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSc90YusEAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXag", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "435b84a2-87aa-43e0-b43b-0e2fc665fc32" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909100728920861213954236204728245768329195052531826", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960996669 + }, + "message": "[WARNING]\t2020-02-17T17:36:36.669Z\t435b84a2-87aa-43e0-b43b-0e2fc665fc32\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960996, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"40947a47-7d0c-48d6-bedf-3765e37ef1e3\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:36.669Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSfF0YusEQAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXaw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "435b84a2-87aa-43e0-b43b-0e2fc665fc32" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909103784122953412649606595121649121154721371848819", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960996805 + }, + "message": "[WARNING]\t2020-02-17T17:36:36.805Z\t435b84a2-87aa-43e0-b43b-0e2fc665fc32\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960996, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"78099195-41f3-4e26-8af4-d27b15b7840a\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:36.805Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOSfJ0YusGAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXcg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909103851025189008241476019728803939099805889790074", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960996809 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:36.809Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOTKh0YusHAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXdg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "31e2c600-7c32-4258-94d5-ed98d8e47e3d" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909165757893860129251316922882728810951346491424894", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960999585 + }, + "message": "[WARNING]\t2020-02-17T17:36:39.585Z\t31e2c600-7c32-4258-94d5-ed98d8e47e3d\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960999, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"49b5d5c1-13d6-44fb-b7c9-e1a9f64edbd1\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:39.585Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOTMi0YusHQAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXdw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "31e2c600-7c32-4258-94d5-ed98d8e47e3d" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909168634689990739701702180990385982589980762898559", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960999714 + }, + "message": "[WARNING]\t2020-02-17T17:36:39.714Z\t31e2c600-7c32-4258-94d5-ed98d8e47e3d\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581960999, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"66a2e4b9-9622-45a1-a27c-d335492c9328\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:36:39.714Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOTMm0YusJAAAAABBWEJVT1ZLQzR4YWdPZVNQQmNXMw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278909168723892971533824194747133259073183426786820230", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581960999718 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:36:39.718Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjK47CjJHQAAAABBWEJVT25LaU5VNGJ4LUE3NUdDVw", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "c7f4482d-c43d-4997-a3b7-3dad41886604" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910627794749075796904565143397822812163733898723328", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961065144 + }, + "message": "[WARNING]\t2020-02-17T17:37:45.144Z\tc7f4482d-c43d-4997-a3b7-3dad41886604\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961064, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"d707ca40-fbba-4524-bb54-c179882959b5\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:45.144Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjM47CjJHgAAAABBWEJVT25LaU5VNGJ4LUE3NUdDWA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "c7f4482d-c43d-4997-a3b7-3dad41886604" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910630649244461208824327259969761711154006664216577", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961065272 + }, + "message": "[WARNING]\t2020-02-17T17:37:45.272Z\tc7f4482d-c43d-4997-a3b7-3dad41886604\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961065, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"fd3f841a-71f3-4590-9c5c-d9c5b1f418d5\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:45.272Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjM87CjJJQAAAABBWEJVT25LaU5VNGJ4LUE3NUdDZQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910630716146696804416196684576916529099091182157832", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961065276 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:37:45.276Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjYD7CjJKQAAAABBWEJVT25MM05VNGJ4LUE3NUdmWg", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a3c23d3a-c7b6-4bea-b56c-2fe3e23d0f4b" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910646571976532959689250316472608382084121934233612", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961065987 + }, + "message": "[WARNING]\t2020-02-17T17:37:45.987Z\ta3c23d3a-c7b6-4bea-b56c-2fe3e23d0f4b\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961065, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"c6084819-e304-4277-8b15-d07dec2ebeee\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:45.987Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjaE7CjJKgAAAABBWEJVT25MM05VNGJ4LUE3NUdmYQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "a3c23d3a-c7b6-4bea-b56c-2fe3e23d0f4b" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910649448772663570139635574580265553722756205707277", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961066116 + }, + "message": "[WARNING]\t2020-02-17T17:37:46.116Z\ta3c23d3a-c7b6-4bea-b56c-2fe3e23d0f4b\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961065, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"de994b4c-55ba-4400-bc5e-cd2a19e92378\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:46.116Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjaJ7CjJMQAAAABBWEJVT25MM05VNGJ4LUE3NUdmaA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910649560276389562792751282258856916964563735609364", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961066121 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:37:46.121Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjnU7CjJNQAAAABBWEJVT25MM05VNGJ4LUE3NUdmbA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "797c2727-93cb-4d1b-a8bb-7c5c9b40d0bc" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910668359804591924108059596869360759533313277100056", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961066964 + }, + "message": "[WARNING]\t2020-02-17T17:37:46.964Z\t797c2727-93cb-4d1b-a8bb-7c5c9b40d0bc\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961066, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"5beebac9-4756-4c6e-a5e1-2a8247ec196b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:46.964Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOjpZ7CjJPQAAAABBWEJVT25MM05VNGJ4LUE3NUdmdA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910671325803703328680937421119891021765393572495392", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961067097 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:37:47.097Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOj2a7CjJNgAAAABBWEJVT25MM05VNGJ4LUE3NUdmbQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "797c2727-93cb-4d1b-a8bb-7c5c9b40d0bc" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910671236600722534558444854977017931171947548573721", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961067930 + }, + "message": "[WARNING]\t2020-02-17T17:37:47.93Z\t797c2727-93cb-4d1b-a8bb-7c5c9b40d0bc\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961066, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"6e021ff5-2653-4aac-89fa-bd1624a33674\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:47.930Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOj6p7CjJQQAAAABBWEJVT25OTk5VNGJ4LUE3NUd3cA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5e3633d1-3337-471a-bea1-45a76b1285a6" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910695945826402506488885676552864025556496174874660", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961068201 + }, + "message": "[WARNING]\t2020-02-17T17:37:48.201Z\t5e3633d1-3337-471a-bea1-45a76b1285a6\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961068, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"b24e1dfa-0397-4d59-87ea-2fc1fc22117b\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:48.201Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOj8r7CjJQgAAAABBWEJVT25OTk5VNGJ4LUE3NUd3cQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "5e3633d1-3337-471a-bea1-45a76b1285a6" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910698844923278315469894076196239469843491952328741", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961068331 + }, + "message": "[WARNING]\t2020-02-17T17:37:48.331Z\t5e3633d1-3337-471a-bea1-45a76b1285a6\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961068, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"48492fff-6477-41d0-813b-1f518ea927d1\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:37:48.331Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOj8v7CjJSQAAAABBWEJVT25OTk5VNGJ4LUE3NUd3eA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278910698934126259109592386642339112560436937976250412", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961068335 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:37:48.335Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOvz-olgpTAAAAABBWEJVT3YtUUZZNkduTFVZQ2RMLQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "4fa5c502-7734-47f9-85be-7614bcf1c3dd" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278911782549636200911101501410478619824248558506672128", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961116926 + }, + "message": "[WARNING]\t2020-02-17T17:38:36.926Z\t4fa5c502-7734-47f9-85be-7614bcf1c3dd\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961116, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"04d0b9a2-f18c-4c82-9b8f-4c9e665e1c6c\", \"body\": {\"trace\": {\"frames\": [{\"filename\": \"/var/task/chalice/app.py\", \"lineno\": 731, \"method\": \"_get_view_function_response\", \"code\": \"response = view_function(**function_args)\", \"argspec\": [\"self\", \"view_function\", \"function_args\"], \"locals\": {\"headers\": {}, \"function_args\": {}, \"view_function\": \"\", \"self\": \"\"}}, {\"filename\": \"/var/task/app.py\", \"lineno\": 1874, \"method\": \"async_send_admin_welcome\", \"code\": \"1 / 0\", \"locals\": {\"params\": {\"sessionId\": \"123456\"}}}], \"exception\": {\"class\": \"ZeroDivisionError\", \"message\": \"division by zero\"}}}, \"custom\": {\"asayerSessionId\": \"123456\"}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:38:36.926Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOv2B1nf01AAAAABBWEJVT3pvdTJLeXpRX1FIVmRORA", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod" + }, + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278911785471033821918613151291457774968821827287580678", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961117057 + }, + "message": "ZeroDivisionError: [asayer_session_id=123456] division by zero", + "timestamp": "2020-02-17T17:38:37.057Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + }, + { + "id": "AQAAAXBUOv9atLL4TQAAAABBWEJVT3YtaFVreVN1OHh3M1dRRQ", + "content": { + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "attributes": { + "lambda": { + "arn": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "request_id": "4fa5c502-7734-47f9-85be-7614bcf1c3dd" + }, + "level": "WARNING", + "service": "lambda", + "host": "arn:aws:lambda:eu-central-1:998611063711:function:parrot-preprod", + "id": "35278911785404131586323021263680787087390697352578465792", + "aws": { + "awslogs": { + "owner": "998611063711", + "logGroup": "/aws/lambda/parrot-preprod", + "logStream": "2020/02/17/[$LATEST]0c50a28217504eb7b706e8ac1c64b702" + }, + "invoked_function_arn": "arn:aws:lambda:eu-central-1:998611063711:function:serverlessrepo-Datadog-Log-For-loglambdaddfunction-2FEJZRLZFKS", + "function_version": "$LATEST" + }, + "timestamp": 1581961117530 + }, + "message": "[WARNING]\t2020-02-17T17:38:37.53Z\t4fa5c502-7734-47f9-85be-7614bcf1c3dd\tRollbar: over rate limit, data was dropped. Payload was: '{\"access_token\": \"940d9aeee5c84024be6a244fe1965599\", \"data\": {\"timestamp\": 1581961116, \"environment\": \"production\", \"level\": \"error\", \"language\": \"python 3.6.10\", \"notifier\": {\"name\": \"pyrollbar\", \"version\": \"0.14.7\"}, \"uuid\": \"03875b42-dd90-4c74-876a-9c3862910315\", \"body\": {\"message\": {\"body\": \"division by zero\", \"asayerSessionId\": \"123456\"}}, \"server\": {\"host\": \"169.254.36.117\", \"pid\": 1, \"argv\": [\"/var/runtime/awslambda/bootstrap.py\"]}}}'", + "timestamp": "2020-02-17T17:38:37.530Z", + "tags": [ + "functionname:parrot-preprod", + "source:lambda", + "forwardername:serverlessrepo-datadog-log-for-loglambdaddfunction-2fejzrlzfks", + "forwarder_version:1.4.1", + "memorysize:1024", + "functionname:parrot-preprod", + "sourcecategory:aws", + "source:lambda" + ] + } + } + ], + "nextLogId": null, + "status": "done", + "requestId": "c2NEeVF4MWNTaXl2QUVGRDRFMWgyUXx0YlJRWTJnaXNiVEtEaWxEMWp6VGF3" +} diff --git a/backend/services/integrations/integration/elasticsearch.go b/backend/services/integrations/integration/elasticsearch.go new file mode 100644 index 000000000..66389f7b9 --- /dev/null +++ b/backend/services/integrations/integration/elasticsearch.go @@ -0,0 +1,193 @@ +package integration + +import ( + elasticlib "github.com/elastic/go-elasticsearch/v7" + "context" + "time" + "encoding/json" + "fmt" + "bytes" + "strconv" + + "openreplay/backend/pkg/utime" + "openreplay/backend/pkg/messages" +) + + +type elasticsearch struct { + Host string + Port json.Number + ApiKeyId string //`json:"api_key_id"` + ApiKey string //`json:"api_key"` + Indexes string +} + +type elasticsearchLog struct { + Message string + Time time.Time `json:"utc_time"` // Should be parsed automatically from RFC3339 +} + +type elasticResponce struct { + Hits struct { + //Total struct { + // Value int + //} + Hits []struct { + Id string `json:"_id"` + Source json.RawMessage `json:"_source"` + } + } + ScrollId string `json:"_scroll_id"` +} + + +func (es *elasticsearch) Request(c* client) error { + address := es.Host + ":" + es.Port.String() + cfg := elasticlib.Config{ + Addresses: []string{ + address, + }, + Username: es.ApiKeyId, + Password: es.ApiKey, + } + esC, err := elasticlib.NewClient(cfg) + + if err != nil { + return err + } + + // TODO: ping/versions/ client host check + // res0, err := esC.Info() + // if err != nil { + // log.Printf("ELASTIC Error getting info: %s", err) + // } + // defer res0.Body.Close() + // // Check response status + // if res0.IsError() { + // log.Printf("ELASTIC Error: %s", res0.String()) + // } + // log.Printf("ELASTIC Info: %v ", res0.String()) + + gteTs := c.getLastMessageTimestamp() + 1000 // Sec or millisec to add ? + + var buf bytes.Buffer + query := map[string]interface{}{ + "query": map[string]interface{}{ + "bool": map[string]interface{}{ + "filter": []map[string]interface{}{ + map[string]interface{}{ + "match": map[string]interface{} { + "message": map[string]interface{}{ + "query": "openReplaySessionToken=", // asayer_session_id= + }, + }, + }, + map[string]interface{}{ + "range": map[string]interface{} { + "utc_time": map[string]interface{}{ + "gte": strconv.FormatUint(gteTs, 10), + "lte": "now", + }, + }, + }, + map[string]interface{}{ + "term": map[string]interface{}{ + "tags": "error", + }, + }, + }, + }, + }, + } + if err := json.NewEncoder(&buf).Encode(query); err != nil { + return fmt.Errorf("Error encoding the query: %s", err) + } + + res, err := esC.Search( + esC.Search.WithContext(context.Background()), + esC.Search.WithIndex(es.Indexes), + esC.Search.WithSize(1000), + esC.Search.WithScroll(time.Minute * 2), + esC.Search.WithBody(&buf), + esC.Search.WithSort("timestamp:asc"), + ) + if err != nil { + return fmt.Errorf("Error getting response: %s", err) + } + defer res.Body.Close() + if res.IsError() { + var e map[string]interface{} + if err := json.NewDecoder(res.Body).Decode(&e); err != nil { + return fmt.Errorf("Error parsing the response body: %v", err) + } else { + return fmt.Errorf("Elasticsearch [%s] %s: %s", + res.Status(), + e["error"],//.(map[string]interface{})["type"], + e["error"],//.(map[string]interface{})["reason"], + ) + } + } + + for { + var esResp elasticResponce + if err := json.NewDecoder(res.Body).Decode(&esResp); err != nil { + return fmt.Errorf("Error parsing the response body: %s", err) + } + if len(esResp.Hits.Hits) == 0 { + break + } + + for _, hit := range esResp.Hits.Hits { + var esLog elasticsearchLog + if err = json.Unmarshal(hit.Source, &esLog); err != nil { + c.errChan <- err + continue + } + token, err := GetToken(esLog.Message) + if err != nil { + c.errChan <- err + continue + } + //parsedTime, err := time.Parse(time.RFC3339, esLog.Timestamp) + //if err != nil { + // c.errChan <- err + // continue + //} + timestamp := uint64(utime.ToMilliseconds(esLog.Time)) + c.setLastMessageTimestamp(timestamp) + c.evChan <- &SessionErrorEvent{ + //SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "elasticsearch", + Timestamp: timestamp, + Name: hit.Id, // sure? + Payload: string(hit.Source), + }, + } + } + + res, err = esC.Scroll( + esC.Scroll.WithContext(context.Background()), + esC.Scroll.WithScrollID(esResp.ScrollId), + esC.Scroll.WithScroll(time.Minute * 2), + ) + if err != nil { + return fmt.Errorf("Error getting scroll response: %s", err) + } + defer res.Body.Close() + if res.IsError() { + var e map[string]interface{} + if err := json.NewDecoder(res.Body).Decode(&e); err != nil { + return fmt.Errorf("Error parsing the response body: %v", err) + } else { + return fmt.Errorf("Elasticsearch [%s] %s: %s", + res.Status(), + e["error"],//.(map[string]interface{})["type"], + e["error"],//.(map[string]interface{})["reason"], + ) + } + } + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/elasticsearch.json b/backend/services/integrations/integration/elasticsearch.json new file mode 100644 index 000000000..bfeeb2843 --- /dev/null +++ b/backend/services/integrations/integration/elasticsearch.json @@ -0,0 +1,469 @@ +{ + "took" : 2, + "timed_out" : false, + "_shards" : { + "total" : 1, + "successful" : 1, + "skipped" : 0, + "failed" : 0 + }, + "hits" : { + "total" : { + "value" : 10, + "relation" : "eq" + }, + "max_score" : null, + "hits" : [ + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "TaSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://www.elastic-elastic-elastic.com/success/christopher-loria", + "request" : "/elasticsearch", + "agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1", + "extension" : "", + "memory" : null, + "ip" : "245.169.167.67", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]245.169.167.67 - - [2018-08-03T16:20:11.988Z] "GET /elasticsearch HTTP/1.1" 200 9950 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1"""", + "url" : "https://www.elastic.co/downloads/elasticsearch", + "tags" : [ + "success", + "info", + "error" + ], + "geo" : { + "srcdest" : "PK:RW", + "src" : "PK", + "coordinates" : { + "lon" : -76.069, + "lat" : 38.80416667 + }, + "dest" : "RW" + }, + "utc_time" : "2020-02-21T16:20:11.988Z", + "bytes" : 9950, + "machine" : { + "os" : "osx", + "ram" : 18253611008 + }, + "response" : 200, + "clientip" : "245.169.167.67", + "host" : "www.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:20:11.988Z" + }, + "sort" : [ + 1582302011988 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "fKSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://facebook.com/error/charles-fullerton", + "request" : "/elasticsearch", + "agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24", + "extension" : "", + "memory" : null, + "ip" : "26.150.255.63", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]26.150.255.63 - - [2018-08-03T16:20:52.802Z] "GET /elasticsearch HTTP/1.1" 200 7330 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"""", + "url" : "https://www.elastic.co/downloads/elasticsearch", + "tags" : [ + "success", + "info", + "error" + ], + "geo" : { + "srcdest" : "US:FR", + "src" : "US", + "coordinates" : { + "lon" : -82.70288889, + "lat" : 34.80997222 + }, + "dest" : "FR" + }, + "utc_time" : "2020-02-21T16:20:52.802Z", + "bytes" : 7330, + "machine" : { + "os" : "ios", + "ram" : 17179869184 + }, + "response" : 200, + "clientip" : "26.150.255.63", + "host" : "www.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:20:52.802Z" + }, + "sort" : [ + 1582302052802 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "QqSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://nytimes.com/warning/yelena-kondakova", + "request" : "/enterprise", + "agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1", + "extension" : "", + "memory" : null, + "ip" : "6.63.231.192", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]6.63.231.192 - - [2018-08-03T16:24:33.154Z] "GET /enterprise HTTP/1.1" 503 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1"""", + "url" : "https://www.elastic.co/downloads/enterprise", + "tags" : [ + "success", + "login", + "error" + ], + "geo" : { + "srcdest" : "BR:IN", + "src" : "BR", + "coordinates" : { + "lon" : -91.67833333, + "lat" : 40.12916667 + }, + "dest" : "IN" + }, + "utc_time" : "2020-02-21T16:24:33.154Z", + "bytes" : 0, + "machine" : { + "os" : "osx", + "ram" : 21474836480 + }, + "response" : 503, + "clientip" : "6.63.231.192", + "host" : "www.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:24:33.154Z" + }, + "sort" : [ + 1582302273154 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "t6SPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://nytimes.com/success/ronald-grabe", + "request" : "/", + "agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24", + "extension" : "", + "memory" : null, + "ip" : "111.58.155.54", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]111.58.155.54 - - [2018-08-03T16:26:12.645Z] "GET / HTTP/1.1" 200 3354 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"""", + "url" : "https://www.elastic.co/downloads", + "tags" : [ + "success", + "info", + "error" + ], + "geo" : { + "srcdest" : "CN:CN", + "src" : "CN", + "coordinates" : { + "lon" : -93.30739306, + "lat" : 31.99071694 + }, + "dest" : "CN" + }, + "utc_time" : "2020-02-21T16:26:12.645Z", + "bytes" : 3354, + "machine" : { + "os" : "win 8", + "ram" : 9663676416 + }, + "response" : 200, + "clientip" : "111.58.155.54", + "host" : "www.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:26:12.645Z" + }, + "sort" : [ + 1582302372645 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "lqSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://www.elastic-elastic-elastic.com/warning/gregory-h-johnson", + "request" : "/styles/ad-blocker.css", + "agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24", + "extension" : "css", + "memory" : null, + "ip" : "85.130.95.75", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]85.130.95.75 - - [2018-08-03T16:36:29.881Z] "GET /styles/ad-blocker.css HTTP/1.1" 200 7755 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"""", + "url" : "https://cdn.elastic-elastic-elastic.org/styles/ad-blocker.css", + "tags" : [ + "warning", + "login", + "error" + ], + "geo" : { + "srcdest" : "US:CD", + "src" : "US", + "coordinates" : { + "lon" : -80.09559417, + "lat" : 26.68316194 + }, + "dest" : "CD" + }, + "utc_time" : "2020-02-21T16:36:29.881Z", + "bytes" : 7755, + "machine" : { + "os" : "win 8", + "ram" : 18253611008 + }, + "response" : 200, + "clientip" : "85.130.95.75", + "host" : "cdn.elastic-elastic-elastic.org", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:36:29.881Z" + }, + "sort" : [ + 1582302989881 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "qqSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://nytimes.com/success/liu-wang", + "request" : "/elasticsearch", + "agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1", + "extension" : "", + "memory" : null, + "ip" : "107.238.94.231", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]107.238.94.231 - - [2018-08-03T16:52:30.202Z] "GET /elasticsearch HTTP/1.1" 503 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1"""", + "url" : "https://www.elastic.co/downloads/elasticsearch", + "tags" : [ + "success", + "security", + "error" + ], + "geo" : { + "srcdest" : "CN:BR", + "src" : "CN", + "coordinates" : { + "lon" : -85.24216667, + "lat" : 37.63355556 + }, + "dest" : "BR" + }, + "utc_time" : "2020-02-21T16:52:30.202Z", + "bytes" : 0, + "machine" : { + "os" : "osx", + "ram" : 9663676416 + }, + "response" : 503, + "clientip" : "107.238.94.231", + "host" : "www.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:52:30.202Z" + }, + "sort" : [ + 1582303950202 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "5KSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://facebook.com/success/edward-gibson", + "request" : "/beats/filebeat", + "agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24", + "extension" : "", + "memory" : null, + "ip" : "231.185.3.235", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]231.185.3.235 - - [2018-08-03T16:54:58.604Z] "GET /beats/filebeat HTTP/1.1" 200 7616 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"""", + "url" : "https://www.elastic.co/downloads/beats/filebeat", + "tags" : [ + "success", + "security", + "error" + ], + "geo" : { + "srcdest" : "BO:IN", + "src" : "BO", + "coordinates" : { + "lon" : -151.1913661, + "lat" : 61.965295 + }, + "dest" : "IN" + }, + "utc_time" : "2020-02-21T16:54:58.604Z", + "bytes" : 7616, + "machine" : { + "os" : "osx", + "ram" : 13958643712 + }, + "response" : 200, + "clientip" : "231.185.3.235", + "host" : "www.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T16:54:58.604Z" + }, + "sort" : [ + 1582304098604 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "6aSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://www.elastic-elastic-elastic.com/success/umberto-guidoni", + "request" : "/beats/filebeat/filebeat-6.3.2-linux-x86.tar.gz", + "agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24", + "extension" : "gz", + "memory" : null, + "ip" : "251.250.144.158", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]251.250.144.158 - - [2018-08-03T17:01:11.333Z] "GET /beats/filebeat/filebeat-6.3.2-linux-x86.tar.gz HTTP/1.1" 200 9860 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"""", + "url" : "https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.3.2-linux-x86.tar.gz", + "tags" : [ + "success", + "info", + "error" + ], + "geo" : { + "srcdest" : "IN:IT", + "src" : "IN", + "coordinates" : { + "lon" : -92.464455, + "lat" : 39.72870694 + }, + "dest" : "IT" + }, + "utc_time" : "2020-02-21T17:01:11.333Z", + "bytes" : 9860, + "machine" : { + "os" : "ios", + "ram" : 6442450944 + }, + "response" : 200, + "clientip" : "251.250.144.158", + "host" : "artifacts.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T17:01:11.333Z" + }, + "sort" : [ + 1582304471333 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "uaSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://www.elastic-elastic-elastic.com/success/daniel-barry", + "request" : "/kibana/kibana-6.3.2-linux-x86_64.tar.gz", + "agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1", + "extension" : "gz", + "memory" : null, + "ip" : "247.50.93.227", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]247.50.93.227 - - [2018-08-03T17:08:38.706Z] "GET /kibana/kibana-6.3.2-linux-x86_64.tar.gz HTTP/1.1" 200 3119 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1"""", + "url" : "https://artifacts.elastic.co/downloads/kibana/kibana-6.3.2-linux-x86_64.tar.gz", + "tags" : [ + "success", + "info", + "error" + ], + "geo" : { + "srcdest" : "IN:US", + "src" : "IN", + "coordinates" : { + "lon" : -90.32484722, + "lat" : 36.77394444 + }, + "dest" : "US" + }, + "utc_time" : "2020-02-21T17:08:38.706Z", + "bytes" : 3119, + "machine" : { + "os" : "osx", + "ram" : 9663676416 + }, + "response" : 200, + "clientip" : "247.50.93.227", + "host" : "artifacts.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T17:08:38.706Z" + }, + "sort" : [ + 1582304918706 + ] + }, + { + "_index" : "kibana_sample_data_logs", + "_type" : "_doc", + "_id" : "MKSPaHABZ3Nzf4SJcTnh", + "_score" : null, + "_source" : { + "referer" : "http://twitter.com/success/anthony-w-england", + "request" : "/elasticsearch/elasticsearch-6.3.2.zip", + "agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24", + "extension" : "zip", + "memory" : null, + "ip" : "179.153.116.46", + "index" : "kibana_sample_data_logs", + "message" : """[asayer_session_id=123456677890]179.153.116.46 - - [2018-08-03T17:11:18.968Z] "GET /elasticsearch/elasticsearch-6.3.2.zip HTTP/1.1" 200 4685 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"""", + "url" : "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.zip", + "tags" : [ + "success", + "info", + "error" + ], + "geo" : { + "srcdest" : "IN:IT", + "src" : "IN", + "coordinates" : { + "lon" : -97.10931306, + "lat" : 40.86525806 + }, + "dest" : "IT" + }, + "utc_time" : "2020-02-21T17:11:18.968Z", + "bytes" : 4685, + "machine" : { + "os" : "ios", + "ram" : 4294967296 + }, + "response" : 200, + "clientip" : "179.153.116.46", + "host" : "artifacts.elastic.co", + "phpmemory" : null, + "timestamp" : "2020-02-21T17:11:18.968Z" + }, + "sort" : [ + 1582305078968 + ] + } + ] + } +} diff --git a/backend/services/integrations/integration/newrelic.go b/backend/services/integrations/integration/newrelic.go new file mode 100644 index 000000000..937ab166d --- /dev/null +++ b/backend/services/integrations/integration/newrelic.go @@ -0,0 +1,104 @@ +package integration + +import ( + "encoding/json" + "time" + "fmt" + "net/http" + "io" + "io/ioutil" + "errors" + + "openreplay/backend/pkg/messages" +) + +/* + We use insights-api for query. They also have Logs and Events +*/ + + +// TODO: Eu/us +type newrelic struct { + ApplicationId string //`json:"application_id"` + XQueryKey string //`json:"x_query_key"` +} + +// TODO: Recheck +type newrelicResponce struct { + Results []struct { + Events []json.RawMessage + } + // Metadata +} + +type newrelicEvent struct { + //AsayerSessionID uint64 `json:"asayer_session_id,string"` // string/int decoder? + OpenReplaySessionToken string `json:"openReplaySessionToken"` + ErrorClass string `json:"error.class"` + Timestamp uint64 `json:"timestamp"` +} + +func (nr *newrelic) Request(c *client) error { + sinceTs := c.getLastMessageTimestamp() + 1000 // From next second + // In docs - format "yyyy-mm-dd HH:MM:ss", but time.RFC3339 works fine too + sinceFormatted := time.Unix(0, int64(sinceTs*1e6)).Format(time.RFC3339) + // US/EU endpoint ?? + requestURL := fmt.Sprintf("https://insights-api.eu.newrelic.com/v1/accounts/%v/query", nr.ApplicationId) + req, err := http.NewRequest("GET", requestURL, nil) + if err != nil { + return err + } + + // The docks and api are awfull. Seems like SINCE works inclusively. + nrql := fmt.Sprintf("SELECT * FROM TransactionError SINCE '%v' WHERE openReplaySessionToken IS NOT NULL", sinceFormatted) + q := req.URL.Query() + q.Add("nrql", nrql) + req.URL.RawQuery = q.Encode() + + req.Header.Add("X-Query-Key", nr.XQueryKey) + req.Header.Add("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + + // 401 (unauthorised) if wrong XQueryKey/deploymentServer is wrong or 403 (Forbidden) if ApplicationId is wrong + // 400 if Query has problems + if resp.StatusCode >= 400 { + io.Copy(ioutil.Discard, resp.Body) // Read the body to free socket + return fmt.Errorf("Newrelic: server respond with the code %v| Request: ", resp.StatusCode, *req) + } + // Pagination depending on returning metadata ? + var nrResp newrelicResponce + if err = json.NewDecoder(resp.Body).Decode(&nrResp); err != nil { + return err + } + for _, r := range nrResp.Results { + for _, jsonEvent := range r.Events { + var e newrelicEvent + if err = json.Unmarshal(jsonEvent, &e); err != nil { + c.errChan <- err + continue + } + if e.OpenReplaySessionToken == "" { + c.errChan <- errors.New("Token is empty") + continue + } + + c.setLastMessageTimestamp(e.Timestamp) + c.evChan <- &SessionErrorEvent{ + Token: e.OpenReplaySessionToken, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "newrelic", + Timestamp: e.Timestamp, + Name: e.ErrorClass, + Payload: string(jsonEvent), + }, + } + } + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/newrelic.json b/backend/services/integrations/integration/newrelic.json new file mode 100644 index 000000000..2730220e8 --- /dev/null +++ b/backend/services/integrations/integration/newrelic.json @@ -0,0 +1,153 @@ +{ + "results": [ + { + "events": [ + { + "aggregateFacet": "WebTransaction/Function/flaskr.auth:register::builtins:ZeroDivisionError", + "appId": 28925082, + "appName": "My Flask Python Application", + "duration": 0.0017523765563964844, + "entityGuid": "MjYyNzMzN3xBUE18QVBQTElDQVRJT058Mjg5MjUwODI", + "error.class": "builtins:ZeroDivisionError", + "error.message": "division by zero", + "host": "new-relic-flask2", + "port": 8080, + "realAgentId": 28925084, + "request.headers.accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "request.headers.host": "35.236.108.92:8080", + "request.headers.referer": "http://35.236.108.92:8080/", + "request.headers.userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36", + "request.method": "GET", + "request.uri": "/auth/register", + "thread.concurrency": 0.9917959662585014, + "timestamp": 1582133149351, + "transactionName": "WebTransaction/Function/flaskr.auth:register", + "transactionUiName": "/flaskr.auth:register" + }, + { + "aggregateFacet": "WebTransaction/Function/flaskr.auth:register::builtins:ZeroDivisionError", + "appId": 28925082, + "appName": "My Flask Python Application", + "duration": 0.0011684894561767578, + "entityGuid": "MjYyNzMzN3xBUE18QVBQTElDQVRJT058Mjg5MjUwODI", + "error.class": "builtins:ZeroDivisionError", + "error.message": "division by zero", + "host": "new-relic-flask2", + "port": 8080, + "realAgentId": 28925084, + "request.headers.accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "request.headers.host": "35.236.108.92:8080", + "request.headers.referer": "http://35.236.108.92:8080/", + "request.headers.userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36", + "request.method": "GET", + "request.uri": "/auth/register", + "thread.concurrency": 0.9858882285247911, + "timestamp": 1582133148418, + "transactionName": "WebTransaction/Function/flaskr.auth:register", + "transactionUiName": "/flaskr.auth:register" + }, + { + "aggregateFacet": "WebTransaction/Function/flaskr.auth:register::builtins:ZeroDivisionError", + "appId": 28925082, + "appName": "My Flask Python Application", + "duration": 0.0011768341064453125, + "entityGuid": "MjYyNzMzN3xBUE18QVBQTElDQVRJT058Mjg5MjUwODI", + "error.class": "builtins:ZeroDivisionError", + "error.message": "division by zero", + "host": "new-relic-flask2", + "port": 8080, + "realAgentId": 28925084, + "request.headers.accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "request.headers.host": "35.236.108.92:8080", + "request.headers.referer": "http://35.236.108.92:8080/", + "request.headers.userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36", + "request.method": "GET", + "request.uri": "/auth/register", + "thread.concurrency": 0.9890943792544556, + "timestamp": 1582133147569, + "transactionName": "WebTransaction/Function/flaskr.auth:register", + "transactionUiName": "/flaskr.auth:register" + }, + { + "aggregateFacet": "WebTransaction/Function/flaskr.auth:register::builtins:ZeroDivisionError", + "appId": 28925082, + "appName": "My Flask Python Application", + "duration": 0.0011293888092041016, + "entityGuid": "MjYyNzMzN3xBUE18QVBQTElDQVRJT058Mjg5MjUwODI", + "error.class": "builtins:ZeroDivisionError", + "error.message": "division by zero", + "host": "new-relic-flask2", + "port": 8080, + "realAgentId": 28925084, + "request.headers.accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "request.headers.host": "35.236.108.92:8080", + "request.headers.referer": "http://35.236.108.92:8080/", + "request.headers.userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36", + "request.method": "GET", + "request.uri": "/auth/register", + "thread.concurrency": 0.986374214903945, + "timestamp": 1582133146601, + "transactionName": "WebTransaction/Function/flaskr.auth:register", + "transactionUiName": "/flaskr.auth:register" + }, + { + "aggregateFacet": "WebTransaction/Function/flaskr.auth:register::builtins:ZeroDivisionError", + "appId": 28925082, + "appName": "My Flask Python Application", + "duration": 0.0011687278747558594, + "entityGuid": "MjYyNzMzN3xBUE18QVBQTElDQVRJT058Mjg5MjUwODI", + "error.class": "builtins:ZeroDivisionError", + "error.message": "division by zero", + "host": "new-relic-flask2", + "port": 8080, + "realAgentId": 28925084, + "request.headers.accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "request.headers.host": "35.236.108.92:8080", + "request.headers.referer": "http://35.236.108.92:8080/", + "request.headers.userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36", + "request.method": "GET", + "request.uri": "/auth/register", + "thread.concurrency": 0.9839758465932258, + "timestamp": 1582133139999, + "transactionName": "WebTransaction/Function/flaskr.auth:register", + "transactionUiName": "/flaskr.auth:register" + } + ] + } + ], + "performanceStats": { + "inspectedCount": 5, + "omittedCount": 0, + "matchCount": 5, + "wallClockTime": 18 + }, + "metadata": { + "eventTypes": [ + "TransactionError" + ], + "eventType": "TransactionError", + "openEnded": false, + "beginTime": "2020-02-18T18:00:00Z", + "endTime": "2020-02-19T19:38:58Z", + "beginTimeMillis": 1582048800000, + "endTimeMillis": 1582141138000, + "rawSince": "'2020-02-18T18:00:00Z'", + "rawUntil": "'2020-02-19T19:38:58Z'", + "rawCompareWith": "", + "guid": "5890296a-5092-5fcc-f05d-b55dbeb8a500", + "routerGuid": "729a50a2-a73f-5d88-cd1f-ea0a9ace54a6", + "messages": [ + "Your query's end time is in the future. Results may be incomplete." + ], + "contents": [ + { + "function": "events", + "limit": 100, + "order": { + "column": "timestamp", + "descending": true + } + } + ] + } +} diff --git a/backend/services/integrations/integration/newrelic_empty.json b/backend/services/integrations/integration/newrelic_empty.json new file mode 100644 index 000000000..1971eb592 --- /dev/null +++ b/backend/services/integrations/integration/newrelic_empty.json @@ -0,0 +1,42 @@ +{ + "results": [ + { + "events": [] + } + ], + "performanceStats": { + "inspectedCount": 0, + "omittedCount": 0, + "matchCount": 0, + "wallClockTime": 10 + }, + "metadata": { + "eventTypes": [ + "TransactionError" + ], + "eventType": "TransactionError", + "openEnded": true, + "beginTime": "2014-08-04T00:00:00Z", + "endTime": "2020-02-14T18:04:23Z", + "beginTimeMillis": 1407110400000, + "endTimeMillis": 1581703463865, + "rawSince": "'2014-08-04 00:00:00'", + "rawUntil": "NOW", + "rawCompareWith": "", + "guid": "27d3fd61-735a-ab46-51b4-f96f07226d2b", + "routerGuid": "979f0b32-b13b-fad1-7577-60f2025da513", + "messages": [ + "No events found -- do you have the correct event type and time range?" + ], + "contents": [ + { + "function": "events", + "limit": 100, + "order": { + "column": "timestamp", + "descending": true + } + } + ] + } +} diff --git a/backend/services/integrations/integration/rollbar.go b/backend/services/integrations/integration/rollbar.go new file mode 100644 index 000000000..369ee31f9 --- /dev/null +++ b/backend/services/integrations/integration/rollbar.go @@ -0,0 +1,176 @@ +package integration + +import ( + "net/http" + "encoding/json" + "fmt" + "time" + "strings" + "strconv" + "io" + "io/ioutil" + "errors" + + "openreplay/backend/pkg/messages" +) + +// Old name: asayerSessionId + +// QUERY: what can be modified? +const RB_QUERY = + "SELECT item.id, item.title,body.message.openReplaySessionToken,item.level,"+ + " item.counter,item.environment,body.crash_report.raw,body.message.body,timestamp"+ + " FROM item_occurrence"+ + " WHERE body.message.openReplaySessionToken != null"+ + " AND timestamp>= %v"+ + " AND item.level>30"+ + " ORDER BY timestamp"+ + " LIMIT 1000" +// ASC by default +// \n\t symbols can spoil the request body, so it wouldn't work (OR probably it happend because of job hashing) + +/* + - `read` Access Token required + - timstamp in seconds +*/ + +type rollbar struct { + AccessToken string // `json:"access_token"` +} + +type rollbarJobResponce struct { + Err int + Message string + Result struct { + Id int + } +} + +type rollbarJobStatusResponce struct { + Err int + Result struct { + Status string + Result struct { + Rows [][] json.Number + Columns[] string + } + } +} + +type rollbarEvent map[string]string + +/* + It is possible to use /api/1/instances (20 per page) + Jobs for the identical requests are hashed +*/ +func (rb *rollbar) Request(c *client) error { + fromTs := c.getLastMessageTimestamp() + 1000 // From next second + c.setLastMessageTimestamp(fromTs) // anti-job-hashing + fromTsSec := fromTs / 1e3 + query := fmt.Sprintf(RB_QUERY, fromTsSec) + jsonBody := fmt.Sprintf(`{ + "access_token": "%v", + "query_string": "%v" + }`, rb.AccessToken, query) + req, err := http.NewRequest("POST", "https://api.rollbar.com/api/1/rql/jobs", strings.NewReader(jsonBody)) + if err != nil { + return err + } + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + // status != 200 || 201 + // status can be 403 then should report about wrong token + if resp.StatusCode >= 400 { + io.Copy(ioutil.Discard, resp.Body) // Read the body to free socket + return fmt.Errorf("Rollbar: server respond with the code %v", resp.StatusCode) + } + + var jobResponce rollbarJobResponce + if err = json.NewDecoder(resp.Body).Decode(&jobResponce); err != nil { + return err + } + if jobResponce.Err != 0 { + return fmt.Errorf("Rollbar job responce error: %v", jobResponce.Message) + } + + requestURL := fmt.Sprintf( + "https://api.rollbar.com/api/1/rql/job/%v?access_token=%v&expand=result", + jobResponce.Result.Id, + rb.AccessToken, + ) + req, err = http.NewRequest("GET", requestURL, nil) + if err != nil { + return err + } + + tick := time.Tick(5 * time.Second) + for { + <- tick + resp, err = http.DefaultClient.Do(req) + if err != nil { + return err // continue + timeout/maxAttempts + } + defer resp.Body.Close() + // status != 200 + var jobStatus rollbarJobStatusResponce + err := json.NewDecoder(resp.Body).Decode(&jobStatus) + if err != nil { + return err + } + + //todo: pagintation; limit: 1000 + + if jobStatus.Result.Status == "success" { + for _, row := range jobStatus.Result.Result.Rows { + e := make(rollbarEvent) + for i, col := range jobStatus.Result.Result.Columns { + //if len(row) <= i { error } + e[ col ] = row[ i ].String() // here I make them all string. That's not good + } + // sessionID, err := strconv.ParseUint(e[ "body.message.asayerSessionId" ], 10, 64) + // if err != nil { + // c.errChan <- err + // continue + // } + if e[ "body.message.openReplaySessionToken" ] == "" { + c.errChan <- errors.New("Token is empty!") + continue + } + payload, err := json.Marshal(e) + if err != nil { + c.errChan <- err + continue + } + timestampSec, err := strconv.ParseUint(e[ "timestamp" ], 10, 64) + if err != nil { + c.errChan <- err + continue + } + timestamp := timestampSec * 1000 + c.setLastMessageTimestamp(timestamp) + c.evChan <- &SessionErrorEvent{ + Token: e[ "body.message.openReplaySessionToken" ], + RawErrorEvent: &messages.RawErrorEvent{ + Source: "rollbar", + Timestamp: timestamp, + Name: e[ "item.title" ], + Payload: string(payload), + }, + } + } + break + } + if jobStatus.Result.Status != "new" && + jobStatus.Result.Status != "running" { + // error + break + } + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/rollbar_error.json b/backend/services/integrations/integration/rollbar_error.json new file mode 100644 index 000000000..95dc591db --- /dev/null +++ b/backend/services/integrations/integration/rollbar_error.json @@ -0,0 +1,4 @@ +{ + "err": 1, + "message": "insufficient privileges: read scope is required but the access token only has post_server_item." +} \ No newline at end of file diff --git a/backend/services/integrations/integration/rollbar_job_result.json b/backend/services/integrations/integration/rollbar_job_result.json new file mode 100644 index 000000000..da88b3a08 --- /dev/null +++ b/backend/services/integrations/integration/rollbar_job_result.json @@ -0,0 +1,63 @@ +{ + "err": 0, + "result": { + "status": "success", + "job_hash": "2d7141f57204ea9cfe59304beed947313b538608", + "result": { + "isSimpleSelect": true, + "errors": [ + ], + "warnings": [ + ], + "executionTime": 0.021143198013305664, + "effectiveTimestamp": 1582125712, + "rowcount": 1, + "rows": [ + [ + 866038147, + "division by zero", + "250250", + 40, + 2, + "production", + null, + "division by zero", + 1582125312, + 115079899839 + ] + ], + "selectionColumns": [ + "item.id", + "item.title", + "body.message.asayerSessionId", + "item.level", + "item.counter", + "item.environment", + "body.crash_report.raw", + "body.message.body", + "timestamp" + ], + "projectIds": [ + 349886 + ], + "columns": [ + "item.id", + "item.title", + "body.message.asayerSessionId", + "item.level", + "item.counter", + "item.environment", + "body.crash_report.raw", + "body.message.body", + "timestamp", + "occurrence_id" + ] + }, + "date_modified": 1582125712, + "query_string": "SELECT item.id, item.title,body.message.asayerSessionId,item.level,item.counter,item.environment,body.crash_report.raw,body.message.body,timestamp FROM item_occurrence WHERE body.message.asayerSessionId != null\tAND timestamp>= 1582124402\tAND item.level>30\tORDER BY timestamp\tLIMIT 1000", + "date_created": 1582125712, + "project_id": 349886, + "id": 82765415, + "project_group_id": 16555 + } +} diff --git a/backend/services/integrations/integration/rollbar_job_start.json b/backend/services/integrations/integration/rollbar_job_start.json new file mode 100644 index 000000000..8d8b5359b --- /dev/null +++ b/backend/services/integrations/integration/rollbar_job_start.json @@ -0,0 +1,13 @@ +{ + "err": 0, + "result": { + "status": "new", + "job_hash": "2d7141f57204ea9cfe59304beed947313b538608", + "date_modified": 1582125712, + "query_string": "SELECT item.id, item.title,body.message.asayerSessionId,item.level,item.counter,item.environment,body.crash_report.raw,body.message.body,timestamp FROM item_occurrence WHERE body.message.asayerSessionId != null\tAND timestamp>= 1582124402\tAND item.level>30\tORDER BY timestamp\tLIMIT 1000", + "date_created": 1582125712, + "project_id": 349886, + "id": 82765415, + "project_group_id": 16555 + } +} diff --git a/backend/services/integrations/integration/sentry.go b/backend/services/integrations/integration/sentry.go new file mode 100644 index 000000000..2ac095a63 --- /dev/null +++ b/backend/services/integrations/integration/sentry.go @@ -0,0 +1,154 @@ +package integration + +import ( + "net/http" + "net/url" + "encoding/json" + "strings" + "fmt" + "time" + "strconv" + "io" + "io/ioutil" + + "openreplay/backend/pkg/utime" + "openreplay/backend/pkg/messages" +) + + +/* + They also have different stuff + Documentation says: + "Note: This endpoint is experimental and may be removed without notice." +*/ + +type sentry struct { + OrganizationSlug string // `json:"organization_slug"` + ProjectSlug string // `json:"project_slug"` + Token string // `json:"token"` +} + +type sentryEvent struct { + Tags []struct { + Key string + Value string `json:"value"` + } + DateCreated string `json:"dateCreated"` // or dateReceived ? + Title string + EventID string `json:"eventID"` +} + + +func (sn *sentry) Request(c *client) error { + requestURL := fmt.Sprintf("https://sentry.io/api/0/projects/%v/%v/events/", sn.OrganizationSlug, sn.ProjectSlug) + req, err := http.NewRequest("GET", requestURL, nil) + if err != nil { + return err + } + authHeader := "Bearer " + sn.Token + req.Header.Add("Authorization", authHeader) + + // by link ? + lastEventId := c.getLastMessageId() + firstEvent := true + +PageLoop: + for { + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode >= 400 { + io.Copy(ioutil.Discard, resp.Body) // Read the body to free socket + return fmt.Errorf("Sentry: server respond with the code %v", resp.StatusCode) + } + + var jsonEventList []json.RawMessage + err = json.NewDecoder(resp.Body).Decode(&jsonEventList) + if err != nil { + return err + } + + for _, jsonEvent := range jsonEventList { + var e sentryEvent + err = json.Unmarshal(jsonEvent, &e) + if err != nil { + c.errChan <- err + continue + } + + if lastEventId == e.EventID { + break PageLoop + } + + parsedTime, err := time.Parse(time.RFC3339, e.DateCreated) + if err != nil { + c.errChan <- fmt.Errorf("%v | Event: %v", err, e) + continue + } + timestamp := uint64(utime.ToMilliseconds(parsedTime)) + // TODO: not to receive all the messages (use default integration timestamp) + if firstEvent { // TODO: reverse range? + c.setLastMessageId(timestamp, e.EventID) + firstEvent = false + } + + var sessionID uint64 + var token string + for _, tag := range e.Tags { + if tag.Key == "OpenreplaySession" { + token = tag.Value + break + } + if tag.Key == "asayer_session_id" { + sessionID, err = strconv.ParseUint(tag.Value, 10, 64) + break + } + } + if err != nil { + c.errChan <- err + continue + } + if sessionID == 0 { // We can't felter them on request + continue + } + + c.evChan <- &SessionErrorEvent{ + SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "sentry", + Timestamp: timestamp, + Name: e.Title, + Payload: string(jsonEvent), + }, + } + } + + // check link before parsing body? + linkHeader := resp.Header.Get("Link") + if linkHeader == "" { + return fmt.Errorf("No Link header found in the responce.") + } + pagInfo := strings.Split(linkHeader, ",") + if len(pagInfo) < 2 { + return fmt.Errorf("Link header format error. Got: '%v'", linkHeader) + } + + nextLinkInfo := pagInfo[ 1 ] + if strings.Contains(nextLinkInfo, `results="false"`) { + break + } + if !strings.Contains(nextLinkInfo, `results="true"`) { + return fmt.Errorf("Link header format error. Results status not found. Got: '%v'", linkHeader) + } + nextLink := GetLinkFromAngularBrackets(nextLinkInfo) + req.URL, err = url.Parse(nextLink) + if err != nil { + return err + } + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/sentry.json b/backend/services/integrations/integration/sentry.json new file mode 100644 index 000000000..c9b791c6d --- /dev/null +++ b/backend/services/integrations/integration/sentry.json @@ -0,0 +1,4438 @@ +[ + { + "eventID": "f07cccf7831043d48e4501d93455d646", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.9.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1", + "key": "trace" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1-89e01ba57559b01c", + "key": "trace.ctx" + }, + { + "value": "89e01ba57559b01c", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:51:14Z", + "user": null, + "message": "", + "id": "f07cccf7831043d48e4501d93455d646", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "d2601fd4b82145f1a8d754a03005688f", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.238.85", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:51:14Z", + "user": null, + "message": "", + "id": "d2601fd4b82145f1a8d754a03005688f", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "a3ffd317170c4708a16fb4a999f39b90", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.152.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "8b2e42df2ada4b4b915deae3a8574a4e", + "key": "trace" + }, + { + "value": "8b2e42df2ada4b4b915deae3a8574a4e-826320136c93cabc", + "key": "trace.ctx" + }, + { + "value": "826320136c93cabc", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:51:14Z", + "user": null, + "message": "", + "id": "a3ffd317170c4708a16fb4a999f39b90", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "997490f56fa941b7b9546ad4493ded8e", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.14.137", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "5c689b0458234e71b56ad1fe57cb00ed", + "key": "trace" + }, + { + "value": "5c689b0458234e71b56ad1fe57cb00ed-aa3761a195b6383e", + "key": "trace.ctx" + }, + { + "value": "aa3761a195b6383e", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:51:14Z", + "user": null, + "message": "", + "id": "997490f56fa941b7b9546ad4493ded8e", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "7387392f77ee4922a57440210e22bca1", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.198.37", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "36f2c208d1724c31a0b40dc3128e21be", + "key": "trace" + }, + { + "value": "36f2c208d1724c31a0b40dc3128e21be-9d1edbc0b4aec2d2", + "key": "trace.ctx" + }, + { + "value": "9d1edbc0b4aec2d2", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:38:15Z", + "user": null, + "message": "", + "id": "7387392f77ee4922a57440210e22bca1", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "008aa9bac3b447539ce6f813880a6204", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.9.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1", + "key": "trace" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1-8064b97f218669e3", + "key": "trace.ctx" + }, + { + "value": "8064b97f218669e3", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:38:15Z", + "user": null, + "message": "", + "id": "008aa9bac3b447539ce6f813880a6204", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "9080b39e779d4b4ebfdc723f1f46339d", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.179.21", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "2d3db3e3dd4e4c84992c7fc6299d2fb9", + "key": "trace" + }, + { + "value": "2d3db3e3dd4e4c84992c7fc6299d2fb9-b4f306612f165f1d", + "key": "trace.ctx" + }, + { + "value": "b4f306612f165f1d", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:38:14Z", + "user": null, + "message": "", + "id": "9080b39e779d4b4ebfdc723f1f46339d", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "7f6b5351867743f9a388d5c20b9123cb", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.9.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1", + "key": "trace" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1-8064b97f218669e3", + "key": "trace.ctx" + }, + { + "value": "8064b97f218669e3", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:38:14Z", + "user": null, + "message": "", + "id": "7f6b5351867743f9a388d5c20b9123cb", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "1540e3198824499c81da4f234088b931", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.52.5", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "61a8ed635f414436bedbb4c7c01f048f", + "key": "trace" + }, + { + "value": "61a8ed635f414436bedbb4c7c01f048f-ae9b1968b73aed0c", + "key": "trace.ctx" + }, + { + "value": "ae9b1968b73aed0c", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:38:14Z", + "user": null, + "message": "", + "id": "1540e3198824499c81da4f234088b931", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "97d968028d5e437e87b025dee96e6a0e", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.52.5", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "61a8ed635f414436bedbb4c7c01f048f", + "key": "trace" + }, + { + "value": "61a8ed635f414436bedbb4c7c01f048f-ae9b1968b73aed0c", + "key": "trace.ctx" + }, + { + "value": "ae9b1968b73aed0c", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:38:06Z", + "user": null, + "message": "", + "id": "97d968028d5e437e87b025dee96e6a0e", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "8414ffb72d574b00a2e183a89b8bbab2", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.238.85", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:46Z", + "user": null, + "message": "", + "id": "8414ffb72d574b00a2e183a89b8bbab2", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "5803d9ec146f4be8a3f5a8d302e8ddf3", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.52.5", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "61a8ed635f414436bedbb4c7c01f048f", + "key": "trace" + }, + { + "value": "61a8ed635f414436bedbb4c7c01f048f-95024f2f40862eeb", + "key": "trace.ctx" + }, + { + "value": "95024f2f40862eeb", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:46Z", + "user": null, + "message": "", + "id": "5803d9ec146f4be8a3f5a8d302e8ddf3", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "47b258ce392749d1970ba8806cfac3af", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.9.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1", + "key": "trace" + }, + { + "value": "91742e607f184afe9e58c3dd43fddcf1-a9971d83e8d39ecc", + "key": "trace.ctx" + }, + { + "value": "a9971d83e8d39ecc", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:46Z", + "user": null, + "message": "", + "id": "47b258ce392749d1970ba8806cfac3af", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "344dc8e9da5b45e79bd366afc726e71b", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.179.21", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "2d3db3e3dd4e4c84992c7fc6299d2fb9", + "key": "trace" + }, + { + "value": "2d3db3e3dd4e4c84992c7fc6299d2fb9-b4f306612f165f1d", + "key": "trace.ctx" + }, + { + "value": "b4f306612f165f1d", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:46Z", + "user": null, + "message": "", + "id": "344dc8e9da5b45e79bd366afc726e71b", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "b8ee9ea891204a02b605b049001315b6", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.9.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:38Z", + "user": null, + "message": "", + "id": "b8ee9ea891204a02b605b049001315b6", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "ad81ff00a30c4d38abb729358bd013ed", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.238.85", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:36Z", + "user": null, + "message": "", + "id": "ad81ff00a30c4d38abb729358bd013ed", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "9a0a2ba486c54b34a30146bc27b4a6d6", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.52.5", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:36Z", + "user": null, + "message": "", + "id": "9a0a2ba486c54b34a30146bc27b4a6d6", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "679ba71075324ab18cd3d42d742ae84d", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.152.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:36Z", + "user": null, + "message": "", + "id": "679ba71075324ab18cd3d42d742ae84d", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "b00313a201034a3db253755c92cd515e", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.198.37", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:10Z", + "user": null, + "message": "", + "id": "b00313a201034a3db253755c92cd515e", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "da3dfb8f7a1e4971ac43444315003f20", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.14.137", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:09Z", + "user": null, + "message": "", + "id": "da3dfb8f7a1e4971ac43444315003f20", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "f6e60cf553bb4d8a949cf11ec1878fd1", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.179.21", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:08Z", + "user": null, + "message": "", + "id": "f6e60cf553bb4d8a949cf11ec1878fd1", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "4a6a45f345df4a35b3b43a21187db677", + "tags": [ + { + "value": "525314475541266774", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.238.85", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-10T05:36:07Z", + "user": null, + "message": "", + "id": "4a6a45f345df4a35b3b43a21187db677", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_494, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "871da51bfd7d4c8f85bba05f7830e34f", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.10", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.210.77", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-07T01:38:41Z", + "user": null, + "message": "Internal Error for ", + "id": "871da51bfd7d4c8f85bba05f7830e34f", + "culprit": "app in login", + "title": "KeyError: 'email'", + "platform": "python", + "location": "app.py", + "crashFile": null, + "event.type": "error", + "groupID": "1430828026" + }, + { + "eventID": "ad9310581f0e40508c3245f75c6613ad", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.151.229", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-05T15:59:49Z", + "user": null, + "message": "Internal Error for ", + "id": "ad9310581f0e40508c3245f75c6613ad", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "RequestError: RequestError(400, 'invalid_index_name_exception', 'Invalid index name [resources_", + "id": "54a3be2a2a3c47fbb0e47192a7676945", + "culprit": "psycopg2.extras in execute", + "title": "TypeError: 'int' object does not support indexing", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1321104332" + }, + { + "eventID": "fd419f7de2334b8d80263ee246bc2757", + "tags": [ + { + "value": "518443449861084160", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.13.157", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-05T11:22:53Z", + "user": null, + "message": "", + "id": "fd419f7de2334b8d80263ee246bc2757", + "culprit": "chalicelib.sessions in search2_pg", + "title": "IndexError: tuple index out of range", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1342967916" + }, + { + "eventID": "259df7fe53094607ac763e43fcdb6490", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.62.229", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-05T10:02:09Z", + "user": null, + "message": "", + "id": "259df7fe53094607ac763e43fcdb6490", + "culprit": "chalicelib.sessions in search_by_metadata", + "title": "KeyError: 454", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1363409660" + }, + { + "eventID": "f4b493e8075145ddbad1bf74d9e097cd", + "tags": [ + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.214.93", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-05T09:25:32Z", + "user": null, + "message": "", + "id": "f4b493e8075145ddbad1bf74d9e097cd", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "4a71fbacc1114ce196df0fb4366429fd", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.214.77", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-05T09:22:35Z", + "user": null, + "message": "Internal Error for ", + "id": "4a71fbacc1114ce196df0fb4366429fd", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "RequestError: RequestError(400, 'invalid_index_name_exception', 'Invalid index name [resources_", + "id": "54898e0197934faab9ab73dea8218244", + "culprit": "psycopg2.extras in execute", + "title": "TypeError: 'int' object does not support indexing", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1321104332" + }, + { + "eventID": "b0f52d9012ef4f85a323c897380634e6", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.60.73", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:14:02Z", + "user": null, + "message": "", + "id": "b0f52d9012ef4f85a323c897380634e6", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "30820461bc274b8383722ed8c0a84e77", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.132.245", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:14:02Z", + "user": null, + "message": "", + "id": "30820461bc274b8383722ed8c0a84e77", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "fdcf7433ce704285a7e97340db850cc7", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.132.245", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:13:49Z", + "user": null, + "message": "", + "id": "fdcf7433ce704285a7e97340db850cc7", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "789d6509476745eb9207ba87eeea0a14", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.60.73", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:13:49Z", + "user": null, + "message": "", + "id": "789d6509476745eb9207ba87eeea0a14", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "a2e9e496e3334e37909628f03740a11d", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.178.125", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:13:47Z", + "user": null, + "message": "", + "id": "a2e9e496e3334e37909628f03740a11d", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "64011a721b774f50b0a757c89a85f54e", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.44.61", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:13:47Z", + "user": null, + "message": "", + "id": "64011a721b774f50b0a757c89a85f54e", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "ea8a88c67cd74825b756d926e0c68067", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.166.189", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:44Z", + "user": null, + "message": "", + "id": "ea8a88c67cd74825b756d926e0c68067", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "3f1449f697674487bd22e41edf7e42c9", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.236.101", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:44Z", + "user": null, + "message": "", + "id": "3f1449f697674487bd22e41edf7e42c9", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "ccb26875e0254082aa8eb0c91ffab3c4", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.109.181", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:42Z", + "user": null, + "message": "", + "id": "ccb26875e0254082aa8eb0c91ffab3c4", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "a2b33db153ab4a01a3938a218602ffce", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.109.181", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:29Z", + "user": null, + "message": "", + "id": "a2b33db153ab4a01a3938a218602ffce", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "6a9a938c7baa4f77be9c0d288949e483", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.236.101", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:29Z", + "user": null, + "message": "", + "id": "6a9a938c7baa4f77be9c0d288949e483", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "1412c00082004f61a88690a719f674d4", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.166.189", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:29Z", + "user": null, + "message": "", + "id": "1412c00082004f61a88690a719f674d4", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "0c36633cecfe45ff8e33f722110dd038", + "tags": [ + { + "value": "517219005934528592", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.137.85", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T15:05:29Z", + "user": null, + "message": "", + "id": "0c36633cecfe45ff8e33f722110dd038", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_483, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "5c944c11c52b4393b32d11dc4192d12e", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.44.61", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-02-04T14:51:34Z", + "user": null, + "message": "Internal Error for ", + "id": "5c944c11c52b4393b32d11dc4192d12e", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "RequestError: RequestError(400, 'invalid_index_name_exception', 'Invalid index name [resources_", + "id": "d4fcbeac21a94c4aa93cbb43e0ca9f69", + "culprit": "psycopg2.extras in execute", + "title": "TypeError: 'int' object does not support indexing", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1321104332" + }, + { + "eventID": "b11f94ca49cc44a9945ac1323af3dac3", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.146.69", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-31T15:39:56Z", + "user": null, + "message": "", + "id": "b11f94ca49cc44a9945ac1323af3dac3", + "culprit": "psycopg2.extras in execute", + "title": "InvalidTextRepresentation: invalid input syntax for integer: \"search\"", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1487659217" + }, + { + "eventID": "1cb8fc38dec044d280c8cc0476189b37", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.219.173", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-31T05:47:45Z", + "user": null, + "message": "", + "id": "1cb8fc38dec044d280c8cc0476189b37", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "8136adbc1f8d4b6abec9a0fcb9156fbc", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.219.173", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-31T05:47:25Z", + "user": null, + "message": "", + "id": "8136adbc1f8d4b6abec9a0fcb9156fbc", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "d82526781cb74d9fafe86b0caae5a50e", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.219.173", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-31T05:46:56Z", + "user": null, + "message": "", + "id": "d82526781cb74d9fafe86b0caae5a50e", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "92cd1ede67f545f989456032d8e9ef2e", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.181.61", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-31T03:16:59Z", + "user": null, + "message": "Internal Error for ", + "id": "92cd1ede67f545f989456032d8e9ef2e", + "culprit": "psycopg2.extras in execute", + "title": "TypeError: 'int' object does not support indexing", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1321104332" + }, + { + "eventID": "aebbbb2dd7ae47bbaba5007064cc1f64", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.35.105", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:41:23Z", + "user": null, + "message": "", + "id": "aebbbb2dd7ae47bbaba5007064cc1f64", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "039279990d1246b180b817239670cce1", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.238.149", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:34:55Z", + "user": null, + "message": "", + "id": "039279990d1246b180b817239670cce1", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "70a34d3638cb4ba98796e8f525d076af", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.112.77", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:34:04Z", + "user": null, + "message": "", + "id": "70a34d3638cb4ba98796e8f525d076af", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "9b09718595244c1f9bdb6c5fae7b2642", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.97.221", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:33:57Z", + "user": null, + "message": "", + "id": "9b09718595244c1f9bdb6c5fae7b2642", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "d49f291e62cd488f8126223cadaf4bf0", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.112.77", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:08:48Z", + "user": null, + "message": "", + "id": "d49f291e62cd488f8126223cadaf4bf0", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "fcd2150f33be4aaea317bee6ab4c5753", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.112.77", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:08:26Z", + "user": null, + "message": "", + "id": "fcd2150f33be4aaea317bee6ab4c5753", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "80276deb85df4d65b6467fed7e2cab9b", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.182.213", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:06:48Z", + "user": null, + "message": "", + "id": "80276deb85df4d65b6467fed7e2cab9b", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "93965953f2054e5cb8dd12343b8e1310", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.35.105", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:04:58Z", + "user": null, + "message": "", + "id": "93965953f2054e5cb8dd12343b8e1310", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "a19aa2b29da94e5c8e79bfd99e28979b", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.96.221", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T12:04:07Z", + "user": null, + "message": "", + "id": "a19aa2b29da94e5c8e79bfd99e28979b", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "c0e4017b1349495f9dde0545aa5f3b41", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.44.189", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T10:02:03Z", + "user": null, + "message": "", + "id": "c0e4017b1349495f9dde0545aa5f3b41", + "culprit": "chalicelib.sessions in search2_pg", + "title": "IndexError: tuple index out of range", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1342967916" + }, + { + "eventID": "26589f5ffbbd4511b5cbc54e1977cb03", + "tags": [ + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.44.189", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-30T09:57:11Z", + "user": null, + "message": "", + "id": "26589f5ffbbd4511b5cbc54e1977cb03", + "culprit": "chalicelib.sessions in search2_pg", + "title": "IndexError: tuple index out of range", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1342967916" + }, + { + "eventID": "60bcb30ad66e431fad1dadc1049e9471", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.32.213", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "9bb4c80672d14d1698763cfde36c938a", + "key": "trace" + }, + { + "value": "9bb4c80672d14d1698763cfde36c938a-9ffd91f46356078b", + "key": "trace.ctx" + }, + { + "value": "9ffd91f46356078b", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:48:00Z", + "user": null, + "message": "", + "id": "60bcb30ad66e431fad1dadc1049e9471", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "63c86a6f9a0d47418451b8bb2bfc85a9", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.32.213", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:44:34Z", + "user": null, + "message": "", + "id": "63c86a6f9a0d47418451b8bb2bfc85a9", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "b2cc1698df4d4391a65906957606b67b", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.180.109", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "34bc65135869438b85c1951ef428bc69", + "key": "trace" + }, + { + "value": "34bc65135869438b85c1951ef428bc69-9db631c2787505cf", + "key": "trace.ctx" + }, + { + "value": "9db631c2787505cf", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:44:26Z", + "user": null, + "message": "", + "id": "b2cc1698df4d4391a65906957606b67b", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "d71f68e590204a27b8ee65b6fce02273", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.32.213", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:43:55Z", + "user": null, + "message": "", + "id": "d71f68e590204a27b8ee65b6fce02273", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "dd5f5c0d689943cf9e8ba84000559e17", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.180.109", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:43:48Z", + "user": null, + "message": "", + "id": "dd5f5c0d689943cf9e8ba84000559e17", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "fe0b3a8c3c8540fbb0f931596419b128", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.242.205", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "f8aa019bc95d42d6bc3124462d8b91f6", + "key": "trace" + }, + { + "value": "f8aa019bc95d42d6bc3124462d8b91f6-b07924e62d9973a0", + "key": "trace.ctx" + }, + { + "value": "b07924e62d9973a0", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:43:39Z", + "user": null, + "message": "", + "id": "fe0b3a8c3c8540fbb0f931596419b128", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "720cfec0987c4d1aa5db1902201db587", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.70.253", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "09cd4e6592ac4025a6d22b9235cec8d6", + "key": "trace" + }, + { + "value": "09cd4e6592ac4025a6d22b9235cec8d6-bd58b560cda37495", + "key": "trace.ctx" + }, + { + "value": "bd58b560cda37495", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:43:20Z", + "user": null, + "message": "", + "id": "720cfec0987c4d1aa5db1902201db587", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "19e8db755d1149f2bf393669912aaaf1", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.70.253", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:42:35Z", + "user": null, + "message": "", + "id": "19e8db755d1149f2bf393669912aaaf1", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "4a2d46c549a344e989197cf106fb914e", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.242.205", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:42:23Z", + "user": null, + "message": "", + "id": "4a2d46c549a344e989197cf106fb914e", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "1ee2a3e3f74d45f0a75288eb312e34c5", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.132.69", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:41:15Z", + "user": null, + "message": "", + "id": "1ee2a3e3f74d45f0a75288eb312e34c5", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column s.console_log_count does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1355521385" + }, + { + "eventID": "e6b6417f26d24b2ea25c575bd09e0aa5", + "tags": [ + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.180.109", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:23:49Z", + "user": null, + "message": "", + "id": "e6b6417f26d24b2ea25c575bd09e0aa5", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "e288fbe341f34f069136ef7b4feef46b", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.180.109", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:23:15Z", + "user": null, + "message": "Internal Error for ", + "id": "e288fbe341f34f069136ef7b4feef46b", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "RequestError: RequestError(400, 'invalid_index_name_exception', 'Invalid index name [resources_", + "id": "8df03f0f93224369a4555a56e43a340a", + "culprit": "psycopg2.extras in execute", + "title": "TypeError: 'int' object does not support indexing", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1321104332" + }, + { + "eventID": "a4ca36db2ec540b0b11992f720e4338f", + "tags": [ + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.23.109", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:23:12Z", + "user": null, + "message": "", + "id": "a4ca36db2ec540b0b11992f720e4338f", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "afc1816db4fb4127ae5e3102f408bd56", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.23.109", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:22:12Z", + "user": null, + "message": "Internal Error for ", + "id": "afc1816db4fb4127ae5e3102f408bd56", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "RequestError: RequestError(400, 'invalid_index_name_exception', 'Invalid index name [resources_", + "id": "423d5cbb1e07428baa6575fd394b014e", + "culprit": "psycopg2.extras in execute", + "title": "TypeError: 'int' object does not support indexing", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1321104332" + }, + { + "eventID": "e32635c1c97a4de78e3edc2f6b683a79", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.126.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:14:27Z", + "user": null, + "message": "", + "id": "e32635c1c97a4de78e3edc2f6b683a79", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "8df9ffd4acdd466785a4acb767441cea", + "tags": [ + { + "value": "496927055579173623", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.126.29", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T15:10:41Z", + "user": null, + "message": "", + "id": "8df9ffd4acdd466785a4acb767441cea", + "culprit": "psycopg2.extras in execute", + "title": "UndefinedColumn: column \"filters\" of relation \"filters\" does not exist", + "platform": "python", + "location": "psycopg2/extras.py", + "crashFile": null, + "event.type": "error", + "groupID": "1306789194" + }, + { + "eventID": "43843ccce0904d30a6de81d16aff2fd2", + "tags": [ + { + "value": "496888723695543585", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.13.157", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "3d3e4136eb7f4db69f3f28d847745782", + "key": "trace" + }, + { + "value": "3d3e4136eb7f4db69f3f28d847745782-a5596feb6edcf697", + "key": "trace.ctx" + }, + { + "value": "a5596feb6edcf697", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T14:35:56Z", + "user": null, + "message": "", + "id": "43843ccce0904d30a6de81d16aff2fd2", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "75506c1c20c64431a24cf3a0c918fce1", + "tags": [ + { + "value": "496888723695543585", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.13.157", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "3d3e4136eb7f4db69f3f28d847745782", + "key": "trace" + }, + { + "value": "3d3e4136eb7f4db69f3f28d847745782-a79977809b88b89c", + "key": "trace.ctx" + }, + { + "value": "a79977809b88b89c", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T14:35:54Z", + "user": null, + "message": "", + "id": "75506c1c20c64431a24cf3a0c918fce1", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "2c86ba13b3cd48188112994e12da7fe4", + "tags": [ + { + "value": "496888723695543585", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.13.157", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + }, + { + "value": "3d3e4136eb7f4db69f3f28d847745782", + "key": "trace" + }, + { + "value": "3d3e4136eb7f4db69f3f28d847745782-873289cca1462152", + "key": "trace.ctx" + }, + { + "value": "873289cca1462152", + "key": "trace.span" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T14:35:47Z", + "user": null, + "message": "", + "id": "2c86ba13b3cd48188112994e12da7fe4", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "aed00b6d56304b468b0851c6a2051f8a", + "tags": [ + { + "value": "496888723695543585", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.13.157", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T14:35:28Z", + "user": null, + "message": "", + "id": "aed00b6d56304b468b0851c6a2051f8a", + "culprit": "chalicelib.sessions in search2_pg", + "title": "ProgrammingError: argument formats can't be mixed", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341564580" + }, + { + "eventID": "a2faad5f419241a0951c63510c1bc532", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.67.141", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:43:13Z", + "user": null, + "message": "", + "id": "a2faad5f419241a0951c63510c1bc532", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "eaf2b36857264f64b7e20f06fb993a91", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.10.205", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:42:39Z", + "user": null, + "message": "", + "id": "eaf2b36857264f64b7e20f06fb993a91", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "648ad2698ef04ab08e9e25b7fc1b307e", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "no", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "threading", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.104.37", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:42:39Z", + "user": null, + "message": "", + "id": "648ad2698ef04ab08e9e25b7fc1b307e", + "culprit": "requests.adapters in send", + "title": "SSLError: HTTPSConnectionPool(host='notify.bugsnag.com', port=443): Max retries exceeded with url: / (Cause...", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1265908049" + }, + { + "eventID": "3bc286b53a2f4a0d8394a0c723153936", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.10.205", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:41:56Z", + "user": null, + "message": "", + "id": "3bc286b53a2f4a0d8394a0c723153936", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_477, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116070824" + }, + { + "eventID": "68af914e0b694dd1986e3f18692b1e70", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.104.37", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:41:53Z", + "user": null, + "message": "", + "id": "68af914e0b694dd1986e3f18692b1e70", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_477, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "65cce0e929bc4a7a92b6344ee2e8b14c", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.67.141", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:41:53Z", + "user": null, + "message": "", + "id": "65cce0e929bc4a7a92b6344ee2e8b14c", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_477, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "5f88471651a349c3b16e13443255618d", + "tags": [ + { + "value": "496539098302424786", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.104.109", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-21T08:41:53Z", + "user": null, + "message": "", + "id": "5f88471651a349c3b16e13443255618d", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_477, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + }, + { + "eventID": "705045e17e144d3b8f7059d121962a63", + "tags": [ + { + "value": "495408099984196478", + "key": "asayer_session_id" + }, + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.87.237", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-20T14:57:47Z", + "user": null, + "message": "Internal Error for ._register_view.._view_func at 0x7f6814a242f0>", + "id": "705045e17e144d3b8f7059d121962a63", + "culprit": "chalicelib.sessions in search_by_metadata", + "title": "KeyError: 454", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1457168623" + }, + { + "eventID": "0236bc697a634270ac5b1dcaab0b571f", + "tags": [ + { + "value": "495408099984196478", + "key": "asayer_session_id" + }, + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "rollbar", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.87.237", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-20T14:57:46Z", + "user": null, + "message": "Exception while posting item \"ReadTimeout(ReadTimeoutError(\\\"HTTPSConnectionPool(host='api.rollbar.com', port=443): Read timed out. (read timeout=3)\\\",),)\"", + "id": "0236bc697a634270ac5b1dcaab0b571f", + "culprit": "requests.adapters in send", + "title": "ReadTimeout: HTTPSConnectionPool(host='api.rollbar.com', port=443): Read timed out. (read timeout=3)", + "platform": "python", + "location": "requests/adapters.py", + "crashFile": null, + "event.type": "error", + "groupID": "1341662732" + }, + { + "eventID": "7a8313d3920a4957b231a4005063adb4", + "tags": [ + { + "value": "495408099984196478", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.87.237", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-20T14:57:33Z", + "user": null, + "message": "", + "id": "7a8313d3920a4957b231a4005063adb4", + "culprit": "chalicelib.sessions in search_by_metadata", + "title": "KeyError: 454", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1363409660" + }, + { + "eventID": "4d9bd0d9c4e64141bf47a113e5a3ebcb", + "tags": [ + { + "value": "495408099984196478", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.215.85", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-20T14:55:07Z", + "user": null, + "message": "", + "id": "4d9bd0d9c4e64141bf47a113e5a3ebcb", + "culprit": "chalicelib.sessions in search_by_metadata", + "title": "KeyError: 454", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1363409660" + }, + { + "eventID": "d7da03a8b0c14a87a0a842a6d1c80802", + "tags": [ + { + "value": "495408099984196478", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.137.37", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-20T14:00:45Z", + "user": null, + "message": "", + "id": "d7da03a8b0c14a87a0a842a6d1c80802", + "culprit": "chalicelib.sessions in search_by_metadata", + "title": "KeyError: 454", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1363409660" + }, + { + "eventID": "37f3b106d22c4a379fc6a08d3895262e", + "tags": [ + { + "value": "495408099984196478", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.42.81", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-20T13:57:27Z", + "user": null, + "message": "", + "id": "37f3b106d22c4a379fc6a08d3895262e", + "culprit": "chalicelib.sessions in search_by_metadata", + "title": "KeyError: 454", + "platform": "python", + "location": "/var/task/chalicelib/sessions.py", + "crashFile": null, + "event.type": "error", + "groupID": "1363409660" + }, + { + "eventID": "7ceff8b3b2d14717a7a084d9bd8b6f0c", + "tags": [ + { + "value": "yes", + "key": "handled" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "parrot", + "key": "logger" + }, + { + "value": "logging", + "key": "mechanism" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.213.61", + "key": "server_name" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-16T17:00:09Z", + "user": null, + "message": "Internal Error for ", + "id": "7ceff8b3b2d14717a7a084d9bd8b6f0c", + "culprit": "app in login", + "title": "KeyError: 'email'", + "platform": "python", + "location": "app.py", + "crashFile": null, + "event.type": "error", + "groupID": "1430828026" + }, + { + "eventID": "f1d6e7bdc7fb45b9a0e7497e04a154b1", + "tags": [ + { + "value": "489170522397413008", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.53.141", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-16T07:18:25Z", + "user": null, + "message": "", + "id": "f1d6e7bdc7fb45b9a0e7497e04a154b1", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_476, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063197" + }, + { + "eventID": "321d91bac073407a8a8db6f1d6f4db9a", + "tags": [ + { + "value": "489170522397413008", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.247.229", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-16T07:18:25Z", + "user": null, + "message": "", + "id": "321d91bac073407a8a8db6f1d6f4db9a", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_476, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116063196" + }, + { + "eventID": "23d88885741a403689f92f26cb1e4808", + "tags": [ + { + "value": "489170522397413008", + "key": "asayer_session_id" + }, + { + "value": "error", + "key": "level" + }, + { + "value": "CPython 3.6.9", + "key": "runtime" + }, + { + "value": "CPython", + "key": "runtime.name" + }, + { + "value": "169.254.75.53", + "key": "server_name" + }, + { + "value": "prod", + "key": "stage" + } + ], + "projectID": "1485249", + "dateCreated": "2020-01-16T07:18:25Z", + "user": null, + "message": "", + "id": "23d88885741a403689f92f26cb1e4808", + "culprit": "elasticsearch.connection.base in _raise_error", + "title": "NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index', resources_476, index_or_alias)", + "platform": "python", + "location": "elasticsearch/connection/base.py", + "crashFile": null, + "event.type": "error", + "groupID": "1116236058" + } +] \ No newline at end of file diff --git a/backend/services/integrations/integration/stackdriver.go b/backend/services/integrations/integration/stackdriver.go new file mode 100644 index 000000000..bb8e3cef9 --- /dev/null +++ b/backend/services/integrations/integration/stackdriver.go @@ -0,0 +1,104 @@ +package integration + + +import ( + "google.golang.org/api/option" + "cloud.google.com/go/logging/logadmin" + "google.golang.org/api/iterator" + + //"strconv" + "encoding/json" + "time" + "fmt" + "context" + + "openreplay/backend/pkg/utime" + "openreplay/backend/pkg/messages" +) + + +// Old: asayerSessionId + +const SD_FILTER_QUERY = ` + logName = "projects/%v/logs/%v" + labels.openReplaySessionToken!=null AND + severity>=ERROR AND + timestamp>="%v" +` + +type stackdriver struct { + ServiceAccountCredentials string // `json:"service_account_credentials"` + LogName string // `json:"log_name"` +} + +type saCreds struct { + ProjectId string `json:"project_id"` +} + +func (sd *stackdriver) Request(c *client) error { + fromTs := c.getLastMessageTimestamp() + 1 // Timestamp is RFC3339Nano, so we take the next millisecond + fromFormatted := time.Unix(0, int64(fromTs *1e6)).Format(time.RFC3339Nano) + ctx := context.Background() + + var parsedCreds saCreds + err := json.Unmarshal([]byte(sd.ServiceAccountCredentials), &parsedCreds) + if err != nil { + return err + } + + opt := option.WithCredentialsJSON([]byte(sd.ServiceAccountCredentials)) + client, err := logadmin.NewClient(ctx, parsedCreds.ProjectId, opt) + if err != nil { + return err + } + defer client.Close() + + filter := fmt.Sprintf(SD_FILTER_QUERY, parsedCreds.ProjectId, sd.LogName, fromFormatted) + // By default, Entries are listed from oldest to newest. + /* ResourceNames(rns []string) + "projects/[PROJECT_ID]" + "organizations/[ORGANIZATION_ID]" + "billingAccounts/[BILLING_ACCOUNT_ID]" + "folders/[FOLDER_ID]" + */ + it := client.Entries(ctx, logadmin.Filter(filter)) + + // TODO: Pagination: + //pager := iterator.NewPager(it, 1000, "") + //nextToken, err := pager.NextPage(&entries) + //if nextToken == "" { break } + for { + e, err := it.Next() + if err == iterator.Done { + break + } + if err != nil { + return err + } + + token := e.Labels["openReplaySessionToken"] + // sessionID, err := strconv.ParseUint(strSessionID, 10, 64) + // if err != nil { + // c.errChan <- err + // continue + // } + jsonEvent, err := json.Marshal(e) + if err != nil { + c.errChan <- err + continue + } + timestamp := uint64(utime.ToMilliseconds(e.Timestamp)) + c.setLastMessageTimestamp(timestamp) + c.evChan <- &SessionErrorEvent{ + //SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "stackdriver", + Timestamp: timestamp, + Name: e.InsertID, // not sure about that + Payload: string(jsonEvent), + }, + } + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/sumologic.go b/backend/services/integrations/integration/sumologic.go new file mode 100644 index 000000000..2660dd6ac --- /dev/null +++ b/backend/services/integrations/integration/sumologic.go @@ -0,0 +1,219 @@ +package integration + +import ( + "net/http" + "time" + "encoding/json" + "fmt" + "strings" + "io" + "io/ioutil" + + "openreplay/backend/pkg/utime" + "openreplay/backend/pkg/messages" +) + +/* + The maximum value for limit is 10,000 messages or 100 MB in total message size, + which means the query may return less than 10,000 messages if you exceed the size limit. + + API Documentation: https://help.sumologic.com/APIs/Search-Job-API/About-the-Search-Job-API +*/ +const SL_LIMIT = 10000 + +type sumologic struct { + AccessId string // `json:"access_id"` + AccessKey string // `json:"access_key"` + cookies []*http.Cookie +} + + +type sumplogicJobResponce struct { + Id string +} + +type sumologicJobStatusResponce struct { + State string + MessageCount int + //PendingErrors []string +} + +type sumologicResponce struct { + Messages [] struct { + Map json.RawMessage + } +} + +type sumologicEvent struct { + Timestamp uint64 `json:"_messagetime,string"` + Raw string `json:"_raw"` +} + +func (sl *sumologic) deleteJob(jobId string, errChan chan<- error) { + requestURL := fmt.Sprintf("https://api.%vsumologic.com/api/v1/search/jobs/%v", "eu.", jobId) + req, err := http.NewRequest("DELETE", requestURL, nil) + if err != nil { + errChan <- fmt.Errorf("Error on DELETE request creation: %v", err) + return + } + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.SetBasicAuth(sl.AccessId, sl.AccessKey) + resp, err := http.DefaultClient.Do(req) + if err != nil { + errChan <- fmt.Errorf("Error on DELETE request: %v", err) + return + } + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() +} + + +func (sl *sumologic) Request(c *client) error { + fromTs := c.getLastMessageTimestamp() + 1 // From next millisecond + toTs := utime.CurrentTimestamp() + requestURL := fmt.Sprintf("https://api.%vsumologic.com/api/v1/search/jobs", "eu.") // deployment server?? + jsonBody := fmt.Sprintf(`{ + "query": "\"openReplaySessionToken=\" AND (*error* OR *fail* OR *exception*)", + "from": %v, + "to": %v + }`, fromTs, toTs) // docs and api are awful. from/to seems to work inclusively + req, err := http.NewRequest("POST", requestURL, strings.NewReader(jsonBody)) + if err != nil { + return err + } + //q := req.URL.Query() + //q.Add("query", "\"asayer_session_id=\" AND (*error* OR *fail* OR *exception*)") + //q.Add("from", ) + //q.Add("to") + //q.Add("timeZone", "UTC") + //q.Add("byReceiptTime", "true") + + for _, cookie := range sl.cookies { + req.AddCookie(cookie) + } + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.SetBasicAuth(sl.AccessId, sl.AccessKey) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return fmt.Errorf("Error while requesting search job start: %v", err) + } + defer resp.Body.Close() + + // Can be 202/400/415 according to docs + // https://help.sumologic.com/APIs/Search-Job-API/About-the-Search-Job-API#status-codes + // responce body is NOT the same as in docs (look at the sumologic_job_start.json) + if resp.StatusCode >= 400 { + io.Copy(ioutil.Discard, resp.Body) // Read the body to free socket + return fmt.Errorf("Sumologic: server respond with the code %v | req %v |Resp: %v", resp.StatusCode, *req, *resp) + } + sl.cookies = resp.Cookies() + + var jobResponce sumplogicJobResponce + if err = json.NewDecoder(resp.Body).Decode(&jobResponce); err != nil { + return fmt.Errorf("Error on parsing responce: %v", err) + } + + defer sl.deleteJob(jobResponce.Id, c.errChan) + + requestURL = fmt.Sprintf("https://api.%vsumologic.com/api/v1/search/jobs/%v", "eu.", jobResponce.Id) + req, err = http.NewRequest("GET", requestURL, nil) + if err != nil { + return err + } + req.Header.Add("Accept", "application/json") + req.SetBasicAuth(sl.AccessId, sl.AccessKey) + for _, cookie := range sl.cookies { + req.AddCookie(cookie) + } + + tick := time.Tick(5 * time.Second) + for { + <- tick + resp, err = http.DefaultClient.Do(req) + if err != nil { + return err // TODO: retry, counter/timeout + } + defer resp.Body.Close() + // TODO: check resp.StatusCode + //sl.cookies = resp.Cookies() TODO? + var jobStatus sumologicJobStatusResponce + err := json.NewDecoder(resp.Body).Decode(&jobStatus) + if err != nil { + return err // TODO: retry, counter/timeout + } + if jobStatus.State == "DONE GATHERING RESULTS" { + offset := 0 + for ;offset < jobStatus.MessageCount; { + requestURL = fmt.Sprintf( + "https://api.%vsumologic.com/api/v1/search/jobs/%v/messages?offset=%v&limit=%v", + "eu.", + jobResponce.Id, + offset, + SL_LIMIT, + ) + req, err = http.NewRequest("GET", requestURL, nil) + if err != nil { + return err // TODO: retry, counter/timeout + } + req.Header.Add("Accept", "application/json") + req.SetBasicAuth(sl.AccessId, sl.AccessKey) + for _, cookie := range sl.cookies { + req.AddCookie(cookie) + } + resp, err = http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + var slResp sumologicResponce + err := json.NewDecoder(resp.Body).Decode(&slResp) + if err != nil { + return err + } + for _, m := range slResp.Messages { + var e sumologicEvent + err = json.Unmarshal(m.Map, &e) + if err != nil { + c.errChan <- err + continue + } + + token, err := GetToken(e.Raw) + if err != nil { + c.errChan <- err + continue + } + name := e.Raw + if len(name) > 20 { + name = name[:20] // not sure about that + } + c.setLastMessageTimestamp(e.Timestamp) + c.evChan <- &SessionErrorEvent{ + //SessionID: sessionID, + Token: token, + RawErrorEvent: &messages.RawErrorEvent{ + Source: "sumologic", + Timestamp: e.Timestamp, + Name: name, + Payload: string(m.Map), //e.Raw ? + }, + } + + } + offset += len(slResp.Messages) + } + break + } + if jobStatus.State != "NOT STARTED" && + jobStatus.State != "GATHERING RESULTS" { + // error + break + } + } + return nil +} \ No newline at end of file diff --git a/backend/services/integrations/integration/sumologic_error.json b/backend/services/integrations/integration/sumologic_error.json new file mode 100644 index 000000000..c48ebd514 --- /dev/null +++ b/backend/services/integrations/integration/sumologic_error.json @@ -0,0 +1,6 @@ +{ +"status": 400, +"id": "EV5YQ-N96Y8-RNDUF", +"code": "searchjob.offset.missing", +"message": "Offset is missing." +} \ No newline at end of file diff --git a/backend/services/integrations/integration/sumologic_job_result.json b/backend/services/integrations/integration/sumologic_job_result.json new file mode 100644 index 000000000..fed5c051f --- /dev/null +++ b/backend/services/integrations/integration/sumologic_job_result.json @@ -0,0 +1,146 @@ +{ + "fields": [ + { + "name": "_blockid", + "fieldType": "long", + "keyField": false + }, + { + "name": "_collector", + "fieldType": "string", + "keyField": false + }, + { + "name": "_collectorid", + "fieldType": "long", + "keyField": false + }, + { + "name": "_format", + "fieldType": "string", + "keyField": false + }, + { + "name": "_messagecount", + "fieldType": "int", + "keyField": false + }, + { + "name": "_messageid", + "fieldType": "long", + "keyField": false + }, + { + "name": "_messagetime", + "fieldType": "long", + "keyField": false + }, + { + "name": "_raw", + "fieldType": "string", + "keyField": false + }, + { + "name": "_receipttime", + "fieldType": "long", + "keyField": false + }, + { + "name": "_size", + "fieldType": "long", + "keyField": false + }, + { + "name": "_source", + "fieldType": "string", + "keyField": false + }, + { + "name": "_sourcecategory", + "fieldType": "string", + "keyField": false + }, + { + "name": "_sourcehost", + "fieldType": "string", + "keyField": false + }, + { + "name": "_sourceid", + "fieldType": "long", + "keyField": false + }, + { + "name": "_sourcename", + "fieldType": "string", + "keyField": false + }, + { + "name": "_view", + "fieldType": "string", + "keyField": false + } + ], + "messages": [ + { + "map": { + "_blockid": "-9223372036854750790", + "_messagetime": "1582286762789", + "_raw": "ZeroDivisionError: [asayer_session_id=9999999999] division by zero", + "_collectorid": "108084884", + "_sourceid": "148051672", + "_collector": "new-relic-flask2", + "_messagecount": "11", + "_sourcehost": "new-relic-flask2", + "_messageid": "-9223372036854423342", + "_sourcename": "/home/tahay_asayer_io/tutorial/example.log", + "_size": "66", + "_view": "", + "_receipttime": "1582286762789", + "_sourcecategory": "linux/system", + "_format": "t:fail:o:-1:l:0:p:null", + "_source": "Linux System_2" + } + }, + { + "map": { + "_blockid": "-9223372036854750791", + "_messagetime": "1582286727679", + "_raw": "ZeroDivisionError: [asayer_session_id=9999999999] division by zero", + "_collectorid": "108084884", + "_sourceid": "148051672", + "_collector": "new-relic-flask2", + "_messagecount": "8", + "_sourcehost": "new-relic-flask2", + "_messageid": "-9223372036854423345", + "_sourcename": "/home/tahay_asayer_io/tutorial/example.log", + "_size": "66", + "_view": "", + "_receipttime": "1582286727679", + "_sourcecategory": "linux/system", + "_format": "t:fail:o:-1:l:0:p:null", + "_source": "Linux System_2" + } + }, + { + "map": { + "_blockid": "-9223372036854750791", + "_messagetime": "1582286723677", + "_raw": "ZeroDivisionError: [asayer_session_id=9999999999] division by zero", + "_collectorid": "108084884", + "_sourceid": "148051672", + "_collector": "new-relic-flask2", + "_messagecount": "5", + "_sourcehost": "new-relic-flask2", + "_messageid": "-9223372036854423348", + "_sourcename": "/home/tahay_asayer_io/tutorial/example.log", + "_size": "66", + "_view": "", + "_receipttime": "1582286723677", + "_sourcecategory": "linux/system", + "_format": "t:fail:o:-1:l:0:p:null", + "_source": "Linux System_2" + } + } + ] +} diff --git a/backend/services/integrations/integration/sumologic_job_start.json b/backend/services/integrations/integration/sumologic_job_start.json new file mode 100644 index 000000000..617571fa2 --- /dev/null +++ b/backend/services/integrations/integration/sumologic_job_start.json @@ -0,0 +1,7 @@ +{ + "id":"6F17F4197B438B68", + "link": { + "rel":"self", + "href":"https://api.eu.sumologic.com/api/v1/search/jobs/6F17F4197B438B68" + } +} \ No newline at end of file diff --git a/backend/services/integrations/integration/sumologic_job_status.json b/backend/services/integrations/integration/sumologic_job_status.json new file mode 100644 index 000000000..2b3c00b88 --- /dev/null +++ b/backend/services/integrations/integration/sumologic_job_status.json @@ -0,0 +1,16 @@ +{ + "state": "DONE GATHERING RESULTS", + "histogramBuckets": [ + { + "startTimestamp": 1582243200000, + "length": 55087270, + "count": 194 + } + ], + "messageCount": 194, + "recordCount": 0, + "pendingWarnings": [ + ], + "pendingErrors": [ + ] +} diff --git a/backend/services/integrations/integration/utils.go b/backend/services/integrations/integration/utils.go new file mode 100644 index 000000000..396a177bd --- /dev/null +++ b/backend/services/integrations/integration/utils.go @@ -0,0 +1,34 @@ +package integration + +import ( + "regexp" + "strconv" + "strings" + "fmt" +) + +var reSessionID = regexp.MustCompile(`(?i)asayer_session_id=([0-9]+)`) +func GetAsayerSessionId(s string) (uint64, error) { + matches := reSessionID.FindStringSubmatch(s) + if len(matches) < 2 { + return 0, fmt.Errorf("'asayer_session_id' not found in '%v' ", s) + } + return strconv.ParseUint(matches[ 1 ], 10, 64) +} + +func GetLinkFromAngularBrackets(s string) string { + beg := strings.Index(s, "<") + 1 + end := strings.Index(s, ">") + if end < 0 { return "" } + return strings.TrimSpace(s[beg:end]) +} + + +var reToken = regexp.MustCompile(`(?i)openReplaySessionToken=([0-9a-zA-Z\.]+)`) +func GetToken(s string) (string, error) { + matches := reToken.FindStringSubmatch(s) + if len(matches) < 2 { + return "", fmt.Errorf("'openReplaySessionToken' not found in '%v' ", s) + } + return matches[ 1 ], nil +} \ No newline at end of file diff --git a/backend/services/integrations/main.go b/backend/services/integrations/main.go new file mode 100644 index 000000000..68b4ec5aa --- /dev/null +++ b/backend/services/integrations/main.go @@ -0,0 +1,99 @@ +package main + +import ( + "log" + "time" + + "os" + "os/signal" + "syscall" + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/intervals" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/pkg/token" + "openreplay/backend/services/integrations/clientManager" +) + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + TOPIC_TRIGGER := env.String("TOPIC_TRIGGER") + POSTGRES_STRING := env.String("POSTGRES_STRING") + + pg := postgres.NewConn(POSTGRES_STRING) + defer pg.Close() + + tokenizer := token.NewTokenizer(env.String("TOKEN_SECRET")) + + manager := clientManager.NewManager() + + pg.IterateIntegrationsOrdered(func(i *postgres.Integration, err error) { + if err != nil { + log.Printf("Postgres error: %v\n", err) + return + } + log.Printf("Integration initialization: %v\n", *i) + err = manager.Update(i) + if err != nil { + log.Printf("Integration parse error: %v | Integration: %v\n", err, *i) + return + } + }) + + producer:= queue.NewProducer() + + listener, err := postgres.NewIntegrationsListener(POSTGRES_STRING) + if err != nil { + log.Fatalf("Postgres listener error: %v\n", err) + } + defer listener.Close() + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + tick := time.Tick(intervals.INTEGRATIONS_REQUEST_INTERVAL * time.Millisecond) + + log.Printf("Integration service started\n") + manager.RequestAll() + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + listener.Close() + pg.Close() + os.Exit(0) + case <-tick: + // log.Printf("Requesting all...\n") + manager.RequestAll() + case event := <-manager.Events: + // log.Printf("New integration event: %v\n", *event.RawErrorEvent) + sessionID := event.SessionID + if sessionID == 0 { + sessData, err := tokenizer.Parse(event.Token) + if err != nil { + log.Printf("Error on token parsing: %v; Token: %v", err, event.Token) + continue + } + sessionID = sessData.ID + } + producer.Produce(TOPIC_TRIGGER, sessionID, messages.Encode(event.RawErrorEvent)) + case err := <-manager.Errors: + log.Printf("Integration error: %v\n", err) + case i := <-manager.RequestDataUpdates: + // log.Printf("Last request integration update: %v || %v\n", i, string(i.RequestData)) + if err := pg.UpdateIntegrationRequestData(&i); err != nil { + log.Printf("Postgres Update request_data error: %v\n", err) + } + //case err := <-listener.Errors: + //log.Printf("Postgres listen error: %v\n", err) + case iPointer := <-listener.Integrations: + // log.Printf("Integration update: %v\n", *iPointer) + err := manager.Update(iPointer) + if err != nil { + log.Printf("Integration parse error: %v | Integration: %v\n", err, *iPointer) + } + } + } +} diff --git a/backend/services/sink/main.go b/backend/services/sink/main.go new file mode 100644 index 000000000..a4f2d6273 --- /dev/null +++ b/backend/services/sink/main.go @@ -0,0 +1,93 @@ +package main + +import ( + "log" + "encoding/binary" + "time" + + "os" + "os/signal" + "syscall" + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/queue/types" +) + + + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + + writer := NewWriter(env.Uint16("FS_ULIMIT"), env.String("FS_DIR")) + + count := 0 + + consumer := queue.NewMessageConsumer( + env.String("GROUP_SINK"), + []string{ + env.String("TOPIC_RAW"), + }, + func(sessionID uint64, message messages.Message, _ *types.Meta) { + //typeID, err := messages.GetMessageTypeID(value) + // if err != nil { + // log.Printf("Message type decoding error: %v", err) + // return + // } + typeID := message.Meta().TypeID + if !messages.IsReplayerType(typeID) { + return + } + + count++ + + value := message.Encode() + var data []byte + if messages.IsIOSType(typeID) { + data = value + } else { + data = make([]byte, len(value)+8) + copy(data[8:], value[:]) + binary.LittleEndian.PutUint64(data[0:], message.Meta().Index) + } + if err := writer.Write(sessionID, data); err != nil { + log.Printf("Writer error: %v\n", err) + } + }, + ) + consumer.DisableAutoCommit() + + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + tick := time.Tick(30 * time.Second) + + log.Println("Start consuming") + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + consumer.Commit() + consumer.Close() + os.Exit(0) + case <-tick: + if err := writer.SyncAll(); err != nil { + log.Fatalf("Sync error: %v\n", err) + } + + log.Printf("%v messages during 30 sec", count) + count = 0 + + consumer.Commit() + default: + err := consumer.ConsumeNext() + if err != nil { + log.Fatalf("Error on consumption: %v", err) + } + } + } + +} + diff --git a/backend/services/sink/writer.go b/backend/services/sink/writer.go new file mode 100644 index 000000000..6fcfdddbc --- /dev/null +++ b/backend/services/sink/writer.go @@ -0,0 +1,99 @@ +package main + +import ( + "math" + "os" + "strconv" + "time" +) + +type Writer struct { + ulimit int + dir string + files map[uint64]*os.File + atimes map[uint64]int64 +} + +func NewWriter(ulimit uint16, dir string) *Writer { + return &Writer{ + ulimit: int(ulimit), + dir: dir + "/", + files: make(map[uint64]*os.File), + atimes: make(map[uint64]int64), + } +} + +func (w *Writer) open(key uint64) (*os.File, error) { + file, ok := w.files[key] + if ok { + return file, nil + } + if len(w.atimes) == w.ulimit { + var m_k uint64 + var m_t int64 = math.MaxInt64 + for k, t := range w.atimes { + if t < m_t { + m_k = k + m_t = t + } + } + if err := w.Close(m_k); err != nil { + return nil, err + } + } + file, err := os.OpenFile(w.dir+strconv.FormatUint(key, 10), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + return nil, err + } + w.files[key] = file + w.atimes[key] = time.Now().Unix() + return file, nil +} + +func (w *Writer) Close(key uint64) error { + file := w.files[key] + if file == nil { + return nil + } + if err := file.Sync(); err != nil { + return err + } + if err := file.Close(); err != nil { + return err + } + delete(w.files, key) + delete(w.atimes, key) + return nil +} + +func (w *Writer) Write(key uint64, data []byte) error { + file, err := w.open(key) + if err != nil { + return err + } + _, err = file.Write(data) + return err +} + +func (w *Writer) SyncAll() error { + for _, file := range w.files { + if err := file.Sync(); err != nil { + return err + } + } + return nil +} + +func (w *Writer) CloseAll() error { + for _, file := range w.files { + if err := file.Sync(); err != nil { + return err + } + if err := file.Close(); err != nil { + return err + } + } + w.files = nil + w.atimes = nil + return nil +} diff --git a/backend/services/storage/gzip.go b/backend/services/storage/gzip.go new file mode 100644 index 000000000..d574ec4ae --- /dev/null +++ b/backend/services/storage/gzip.go @@ -0,0 +1,19 @@ +package main + +import ( + "io" + gzip "github.com/klauspost/pgzip" +) + + +func gzipFile(file io.ReadSeeker) io.Reader { + reader, writer := io.Pipe() + go func() { + gw, _ := gzip.NewWriterLevel(writer, gzip.BestSpeed) + io.Copy(gw, file) + + gw.Close() + writer.Close() + }() + return reader +} \ No newline at end of file diff --git a/backend/services/storage/main.go b/backend/services/storage/main.go new file mode 100644 index 000000000..83337d8a6 --- /dev/null +++ b/backend/services/storage/main.go @@ -0,0 +1,81 @@ +package main + +import ( + "log" + "time" + "os" + "strconv" + + "os/signal" + "syscall" + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/storage" + "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/queue" + "openreplay/backend/pkg/queue/types" +) + + + +func main() { + log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) + + + storageWeb := storage.NewS3(env.String("AWS_REGION_WEB"), env.String("S3_BUCKET_WEB")) + storageIos := storage.NewS3(env.String("AWS_REGION_IOS"), env.String("S3_BUCKET_IOS")) + FS_DIR := env.String("FS_DIR") + "/" + + var uploadKey func(string, int, *storage.S3) + uploadKey = func(key string, retryCount int, s *storage.S3) { + if retryCount <= 0 { + return; + } + file, err := os.Open(FS_DIR + key) + defer file.Close() + if err != nil { + log.Printf("File error: %v; Will retry %v more time(s)\n", err, retryCount) + time.AfterFunc(2*time.Minute, func() { + uploadKey(key, retryCount - 1, s) + }) + } else { + if err := s.Upload(gzipFile(file), key, "application/octet-stream", true); err != nil { + log.Fatalf("Storage upload error: %v\n", err) + } + } + } + + consumer := queue.NewMessageConsumer( + env.String("GROUP_STORAGE"), + []string{ + env.String("TOPIC_TRIGGER"), + }, + func(sessionID uint64, msg messages.Message, meta *types.Meta) { + switch msg.(type) { + case *messages.SessionEnd: + uploadKey(strconv.FormatUint(sessionID, 10), 5, storageWeb) + case *messages.IOSSessionEnd: + uploadKey(strconv.FormatUint(sessionID, 10), 5, storageIos) + } + }, + ) + + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + + log.Println("Start consuming") + for { + select { + case sig := <-sigchan: + log.Printf("Caught signal %v: terminating\n", sig) + consumer.Close() + os.Exit(0) + default: + err := consumer.ConsumeNext() + if err != nil { + log.Fatalf("Error on consumption: %v", err) + } + } + } +} + diff --git a/ee/backend/pkg/db/clickhouse/bulk.go b/ee/backend/pkg/db/clickhouse/bulk.go new file mode 100644 index 000000000..121cdbbf0 --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/bulk.go @@ -0,0 +1,45 @@ +package clickhouse + +import ( + "errors" + "database/sql" +) + +type bulk struct { + db *sql.DB + query string + tx *sql.Tx + stmt *sql.Stmt +} + +func newBulk(db *sql.DB, query string) *bulk { + return &bulk{ + db: db, + query: query, + } +} + +func (b *bulk) prepare() error { + var err error + b.tx, err = b.db.Begin() + if err != nil { + return err + } + b.stmt, err = b.tx.Prepare(b.query) + if err != nil { + return err + } + return nil +} + +func (b *bulk) commit() error { + return b.tx.Commit() +} + +func (b *bulk) exec(args ...interface{}) error { + if b.stmt == nil { + return errors.New("Bulk is not prepared.") + } + _, err := b.stmt.Exec(args...) + return err +} diff --git a/ee/backend/pkg/db/clickhouse/connector.go b/ee/backend/pkg/db/clickhouse/connector.go new file mode 100644 index 000000000..195f2fa48 --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/connector.go @@ -0,0 +1,206 @@ +package clickhouse + +import ( + "log" + "database/sql" + _ "github.com/ClickHouse/clickhouse-go" +) + +type Connector struct { + sessionsIOS *bulk + //viewsIOS *bulk + clicksIOS *bulk + inputsIOS *bulk + crashesIOS *bulk + performanceIOS *bulk + resourcesIOS *bulk + sessions *bulk + metadata *bulk // TODO: join sessions, sessions_metadata & sessions_ios + resources *bulk + pages *bulk + clicks *bulk + inputs *bulk + errors *bulk + performance *bulk + longtasks *bulk +} + +func NewConnector(url string) *Connector { + db, err := sql.Open("clickhouse", url) + if err != nil { + log.Fatalln(err) + } + return &Connector{ + sessionsIOS: newBulk(db, ` + INSERT INTO sessions_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, duration, views_count, events_count, crashes_count, metadata_1, metadata_2, metadata_3, metadata_4, metadata_5, metadata_6, metadata_7, metadata_8, metadata_9, metadata_10) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + // viewsIOS: newBulk(db, ` + // INSERT INTO views_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, url, request_start, response_start, response_end, dom_content_loaded_event_start, dom_content_loaded_event_end, load_event_start, load_event_end, first_paint, first_contentful_paint, speed_index, visually_complete, time_to_interactive) + // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + // `), + clicksIOS: newBulk(db, ` + INSERT INTO clicks_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, label) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + inputsIOS: newBulk(db, ` + INSERT INTO inputs_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, label) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + crashesIOS: newBulk(db, ` + INSERT INTO crashes_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, name, reason, crash_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + performanceIOS: newBulk(db, ` + INSERT INTO performance_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, min_fps, avg_fps, max_fps, min_cpu, avg_cpu, max_cpu, min_memory, avg_memory, max_memory) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + resourcesIOS: newBulk(db, ` + INSERT INTO resources_ios (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, url, duration, body_size, success, method, status) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, nullIf(?, ''), ?) + `), + + sessions: newBulk(db, ` + INSERT INTO sessions (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country, datetime, duration, pages_count, events_count, errors_count, user_browser, user_browser_version) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + // TODO: join sessions, sessions_metadata & sessions_ios + metadata: newBulk(db, ` + INSERT INTO sessions_metadata (session_id, user_id, user_anonymous_id, metadata_1, metadata_2, metadata_3, metadata_4, metadata_5, metadata_6, metadata_7, metadata_8, metadata_9, metadata_10, datetime) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + resources: newBulk(db, ` + INSERT INTO resources (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, url, type, duration, ttfb, header_size, encoded_body_size, decoded_body_size, success, method, status) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + pages: newBulk(db, ` + INSERT INTO pages (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, url, request_start, response_start, response_end, dom_content_loaded_event_start, dom_content_loaded_event_end, load_event_start, load_event_end, first_paint, first_contentful_paint, speed_index, visually_complete, time_to_interactive) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + clicks: newBulk(db, ` + INSERT INTO clicks (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, label, hesitation_time) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + inputs: newBulk(db, ` + INSERT INTO inputs (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, label) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + errors: newBulk(db, ` + INSERT INTO errors (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, source, name, message, error_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + performance: newBulk(db, ` + INSERT INTO performance (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, min_fps, avg_fps, max_fps, min_cpu, avg_cpu, max_cpu, min_total_js_heap_size, avg_total_js_heap_size, max_total_js_heap_size, min_used_js_heap_size, avg_used_js_heap_size, max_used_js_heap_size) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + longtasks: newBulk(db, ` + INSERT INTO longtasks (session_id, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_country, datetime, context, container_type, container_id, container_name, container_src) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `), + + } +} + +func (conn *Connector) Prepare() error { + if err := conn.sessionsIOS.prepare(); err != nil { + return err + } + // if err := conn.viewsIOS.prepare(); err != nil { + // return err + // } + if err := conn.clicksIOS.prepare(); err != nil { + return err + } + if err := conn.inputsIOS.prepare(); err != nil { + return err + } + if err := conn.crashesIOS.prepare(); err != nil { + return err + } + if err := conn.performanceIOS.prepare(); err != nil { + return err + } + if err := conn.resourcesIOS.prepare(); err != nil { + return err + } + if err := conn.sessions.prepare(); err != nil { + return err + } + if err := conn.metadata.prepare(); err != nil { + return err + } + if err := conn.resources.prepare(); err != nil { + return err + } + if err := conn.pages.prepare(); err != nil { + return err + } + if err := conn.clicks.prepare(); err != nil { + return err + } + if err := conn.inputs.prepare(); err != nil { + return err + } + if err := conn.errors.prepare(); err != nil { + return err + } + if err := conn.performance.prepare(); err != nil { + return err + } + if err := conn.longtasks.prepare(); err != nil { + return err + } + return nil +} + +func (conn *Connector) Commit() error { + if err := conn.sessionsIOS.commit(); err != nil { + return err + } + // if err := conn.viewsIOS.commit(); err != nil { + // return err + // } + if err := conn.clicksIOS.commit(); err != nil { + return err + } + if err := conn.inputsIOS.commit(); err != nil { + return err + } + if err := conn.crashesIOS.commit(); err != nil { + return err + } + if err := conn.performanceIOS.commit(); err != nil { + return err + } + if err := conn.resourcesIOS.commit(); err != nil { + return err + } + if err := conn.sessions.commit(); err != nil { + return err + } + if err := conn.metadata.commit(); err != nil { + return err + } + if err := conn.resources.commit(); err != nil { + return err + } + if err := conn.pages.commit(); err != nil { + return err + } + if err := conn.clicks.commit(); err != nil { + return err + } + if err := conn.inputs.commit(); err != nil { + return err + } + if err := conn.errors.commit(); err != nil { + return err + } + if err := conn.performance.commit(); err != nil { + return err + } + if err := conn.longtasks.commit(); err != nil { + return err + } + return nil +} diff --git a/ee/backend/pkg/db/clickhouse/helpers.go b/ee/backend/pkg/db/clickhouse/helpers.go new file mode 100644 index 000000000..37e30518c --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/helpers.go @@ -0,0 +1,34 @@ +package clickhouse + +import ( + "time" +) + + +func nullableUint16(v uint16) *uint16 { + var p *uint16 = nil + if v != 0 { + p = &v + } + return p +} + +func nullableUint32(v uint32) *uint32 { + var p *uint32 = nil + if v != 0 { + p = &v + } + return p +} + +func nullableString(v string) *string { + var p *string = nil + if v != "" { + p = &v + } + return p +} + +func datetime(timestamp uint64) time.Time { + return time.Unix(int64(timestamp/1e3), 0) +} diff --git a/ee/backend/pkg/db/clickhouse/messages_ios.go b/ee/backend/pkg/db/clickhouse/messages_ios.go new file mode 100644 index 000000000..f5ca30495 --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/messages_ios.go @@ -0,0 +1,180 @@ +package clickhouse + +import ( + "errors" + + "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/url" + . "openreplay/backend/pkg/db/types" + . "openreplay/backend/pkg/messages" +) + + +// TODO: join sessions & sessions_ios clcikhouse tables +func (conn *Connector) InsertIOSSession(session *Session) error { + if (session.Duration == nil) { + return errors.New("Clickhouse: trying to insert session with ") + } + return conn.sessionsIOS.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(session.Timestamp), + uint32(*session.Duration), + session.PagesCount, + session.EventsCount, + session.ErrorsCount, + session.Metadata1, + session.Metadata2, + session.Metadata3, + session.Metadata4, + session.Metadata5, + session.Metadata6, + session.Metadata7, + session.Metadata8, + session.Metadata9, + session.Metadata10, + ) +} + +// func (conn *Connector) IOSScreenEnter(session *Session, msg *PageEvent) error { +// return conn.pagesIOS.exec( +// session.SessionID, +// session.ProjectID, +// session.TrackerVersion, nullableString(session.RevID), +// session.UserUUID, +// session.UserOS, +// nullableString(session.UserOSVersion), +// nullableString(session.UserDevice), +// session.UserDeviceType, +// session.UserCountry, +// datetime(msg.Timestamp), +// utils.DiscardURLQuery(msg.URL), +// nullableUint16(uint16(msg.RequestStart)), +// nullableUint16(uint16(msg.ResponseStart)), +// nullableUint16(uint16(msg.ResponseEnd)), +// nullableUint16(uint16(msg.DomContentLoadedEventStart)), +// nullableUint16(uint16(msg.DomContentLoadedEventEnd)), +// nullableUint16(uint16(msg.LoadEventStart)), +// nullableUint16(uint16(msg.LoadEventEnd)), +// nullableUint16(uint16(msg.FirstPaint)), +// nullableUint16(uint16(msg.FirstContentfulPaint)), +// nullableUint16(uint16(msg.SpeedIndex)), +// nullableUint16(uint16(msg.VisuallyComplete)), +// nullableUint16(uint16(msg.TimeToInteractive)), +// ) +// } + +func (conn *Connector) InsertIOSClickEvent(session *Session, msg *IOSClickEvent) error { + if msg.Label == "" { + return nil + } + return conn.clicksIOS.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + msg.Label, + ) +} + +func (conn *Connector) InsertIOSInputEvent(session *Session, msg *IOSInputEvent) error { + if msg.Label == "" { + return nil + } + return conn.inputsIOS.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + msg.Label, + ) +} + +func (conn *Connector) InsertIOSCrash(session *Session, msg *IOSCrash) error { + return conn.crashesIOS.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + msg.Name, + msg.Reason, + hashid.IOSCrashID(session.ProjectID, msg), + ) +} + +func (conn *Connector) InsertIOSNetworkCall(session *Session, msg *IOSNetworkCall) error { + return conn.resourcesIOS.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + url.DiscardURLQuery(msg.URL), + nullableUint16(uint16(msg.Duration)), + nullableUint32(uint32(len(msg.Body))), + msg.Success, + url.EnsureMethod(msg.Method), // nullableString causes error "unexpected type *string" + nullableUint16(uint16(msg.Status)), + ) +} + +func (conn *Connector) InsertIOSPerformanceAggregated(session *Session, msg *IOSPerformanceAggregated) error { + var timestamp uint64 = (msg.TimestampStart + msg.TimestampEnd) / 2 + return conn.performanceIOS.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(timestamp), + uint8(msg.MinFPS), + uint8(msg.AvgFPS), + uint8(msg.MaxFPS), + uint8(msg.MinCPU), + uint8(msg.AvgCPU), + uint8(msg.MaxCPU), + msg.MinMemory, + msg.AvgMemory, + msg.MaxMemory, + ) +} diff --git a/ee/backend/pkg/db/clickhouse/messages_web.go b/ee/backend/pkg/db/clickhouse/messages_web.go new file mode 100644 index 000000000..0c4de6a7b --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/messages_web.go @@ -0,0 +1,246 @@ +package clickhouse + +import ( + "errors" + + "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/url" + . "openreplay/backend/pkg/db/types" + . "openreplay/backend/pkg/messages" +) + + +func (conn *Connector) InsertWebSession(session *Session) error { + if (session.Duration == nil) { + return errors.New("Clickhouse: trying to insert session with ") + } + + if err := conn.sessions.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(session.Timestamp), + uint32(*session.Duration), + session.PagesCount, + session.EventsCount, + session.ErrorsCount, + // Web unique columns + session.UserBrowser, + nullableString(session.UserBrowserVersion), + ); err != nil { + return err + } + // TODO: join sessions, sessions_metadata & sessions_ios + return conn.metadata.exec( + session.SessionID, + session.UserID, + session.UserAnonymousID, + session.Metadata1, + session.Metadata2, + session.Metadata3, + session.Metadata4, + session.Metadata5, + session.Metadata6, + session.Metadata7, + session.Metadata8, + session.Metadata9, + session.Metadata10, + datetime(session.Timestamp), + ) +} + +func (conn *Connector) InsertWebResourceEvent(session *Session, msg *ResourceEvent) error { + // nullableString causes error "unexpected type *string" on Nullable Enum type + // (apparently, a clickhouse-go bug) https://github.com/ClickHouse/clickhouse-go/pull/204 + var method interface{} = url.EnsureMethod(msg.Method) + if method == "" { + method = nil + } + return conn.resources.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + url.DiscardURLQuery(msg.URL), + msg.Type, + nullableUint16(uint16(msg.Duration)), + nullableUint16(uint16(msg.TTFB)), + nullableUint16(uint16(msg.HeaderSize)), + nullableUint32(uint32(msg.EncodedBodySize)), + nullableUint32(uint32(msg.DecodedBodySize)), + msg.Success, + method, + nullableUint16(uint16(msg.Status)), + ) +} + +func (conn *Connector) InsertWebPageEvent(session *Session, msg *PageEvent) error { + return conn.pages.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + url.DiscardURLQuery(msg.URL), + nullableUint16(uint16(msg.RequestStart)), + nullableUint16(uint16(msg.ResponseStart)), + nullableUint16(uint16(msg.ResponseEnd)), + nullableUint16(uint16(msg.DomContentLoadedEventStart)), + nullableUint16(uint16(msg.DomContentLoadedEventEnd)), + nullableUint16(uint16(msg.LoadEventStart)), + nullableUint16(uint16(msg.LoadEventEnd)), + nullableUint16(uint16(msg.FirstPaint)), + nullableUint16(uint16(msg.FirstContentfulPaint)), + nullableUint16(uint16(msg.SpeedIndex)), + nullableUint16(uint16(msg.VisuallyComplete)), + nullableUint16(uint16(msg.TimeToInteractive)), + ) +} + +func (conn *Connector) InsertWebClickEvent(session *Session, msg *ClickEvent) error { + if msg.Label == "" { + return nil + } + return conn.clicks.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + msg.Label, + nullableUint32(uint32(msg.HesitationTime)), + ) +} + +func (conn *Connector) InsertWebInputEvent(session *Session, msg *InputEvent) error { + if msg.Label == "" { + return nil + } + return conn.inputs.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + msg.Label, + ) +} + +func (conn *Connector) InsertWebErrorEvent(session *Session, msg *ErrorEvent) error { + return conn.errors.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + msg.Source, + nullableString(msg.Name), + msg.Message, + hashid.WebErrorID(session.ProjectID, msg), + ) +} + +func (conn *Connector) InsertWebPerformanceTrackAggr(session *Session, msg *PerformanceTrackAggr) error { + var timestamp uint64 = (msg.TimestampStart + msg.TimestampEnd) / 2 + return conn.performance.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(timestamp), + uint8(msg.MinFPS), + uint8(msg.AvgFPS), + uint8(msg.MaxFPS), + uint8(msg.MinCPU), + uint8(msg.AvgCPU), + uint8(msg.MaxCPU), + msg.MinTotalJSHeapSize, + msg.AvgTotalJSHeapSize, + msg.MaxTotalJSHeapSize, + msg.MinUsedJSHeapSize, + msg.AvgUsedJSHeapSize, + msg.MaxUsedJSHeapSize, + ) +} + +// TODO: make enum message type +var CONTEXT_MAP = map[uint64]string{0:"unknown",1:"self",2:"same-origin-ancestor",3:"same-origin-descendant",4:"same-origin",5:"cross-origin-ancestor",6:"cross-origin-descendant",7:"cross-origin-unreachable",8:"multiple-contexts"} +var CONTAINER_TYPE_MAP = map[uint64]string{0:"window",1:"iframe",2:"embed",3:"object"} + +func (conn *Connector) InsertLongtask(session *Session, msg *LongTask) error { + return conn.longtasks.exec( + session.SessionID, + session.ProjectID, + session.TrackerVersion, + nullableString(session.RevID), + session.UserUUID, + session.UserOS, + nullableString(session.UserOSVersion), + session.UserBrowser, + nullableString(session.UserBrowserVersion), + nullableString(session.UserDevice), + session.UserDeviceType, + session.UserCountry, + datetime(msg.Timestamp), + CONTEXT_MAP[ msg.Context ], + CONTAINER_TYPE_MAP[ msg.ContainerType ], + msg.ContainerId, + msg.ContainerName, + msg.ContainerSrc, + ) +} diff --git a/ee/backend/pkg/kafka/consumer.go b/ee/backend/pkg/kafka/consumer.go new file mode 100644 index 000000000..d15f5fa41 --- /dev/null +++ b/ee/backend/pkg/kafka/consumer.go @@ -0,0 +1,238 @@ +package kafka + +import ( + "log" + "os" + // "os/signal" + // "syscall" + "time" + + "github.com/pkg/errors" + + "openreplay/backend/pkg/env" + "openreplay/backend/pkg/queue/types" + "gopkg.in/confluentinc/confluent-kafka-go.v1/kafka" +) + +type Message = kafka.Message + +type Consumer struct { + c *kafka.Consumer + messageHandler types.MessageHandler + commitTicker *time.Ticker + pollTimeout uint + + lastKafkaEventTs int64 + partitions []kafka.TopicPartition +} + +func NewConsumer(group string, topics []string, messageHandler types.MessageHandler) *Consumer { + protocol := "plaintext" + if env.Bool("KAFKA_USE_SSL") { + protocol = "ssl" + } + c, err := kafka.NewConsumer(&kafka.ConfigMap{ + "bootstrap.servers": env.String("KAFKA_SERVERS"), + "group.id": group, + "auto.offset.reset": "earliest", + "enable.auto.commit": "false", + "security.protocol": protocol, + "go.application.rebalance.enable": true, + }) + if err != nil { + log.Fatalln(err) + } + subREx := "^(" + for i, t := range topics { + if i != 0 { + subREx += "|" + } + subREx += t + } + subREx += ")$" + if err := c.Subscribe(subREx, nil); err != nil { + log.Fatalln(err) + } + + return &Consumer{ + c: c, + messageHandler: messageHandler, + commitTicker: time.NewTicker(2 * time.Minute), + pollTimeout: 200, + } +} + +func (consumer *Consumer) DisableAutoCommit() { + consumer.commitTicker.Stop() +} + + +func (consumer *Consumer) Commit() error { + _, err := consumer.c.Commit() + return err +} + +func (consumer *Consumer) CommitBack(gap int64) error { + if consumer.lastKafkaEventTs == 0 || consumer.partitions == nil { + return nil + } + commitTs := consumer.lastKafkaEventTs - gap + var timestamps []kafka.TopicPartition + for _, p := range consumer.partitions { // p is a copy here sinse partition is not a pointer + p.Offset = kafka.Offset(commitTs) + timestamps = append(timestamps, p) + } + offsets, err := consumer.c.OffsetsForTimes(timestamps, 2000) + if err != nil { + return errors.Wrap(err, "Kafka Consumer back commit error") + } + // TODO: check per-partition errors: offsets[i].Error + // As an option: can store offsets and enable autocommit instead + _, err = consumer.c.CommitOffsets(offsets) + return errors.Wrap(err, "Kafka Consumer back commit error") +} + + +func (consumer *Consumer) ConsumeNext() error { + ev := consumer.c.Poll(int(consumer.pollTimeout)) + if ev == nil { + return nil + } + + select { + case <-consumer.commitTicker.C: + consumer.Commit() + default: + } + + switch e := ev.(type) { + case *kafka.Message: + if e.TopicPartition.Error != nil { + return errors.Wrap(e.TopicPartition.Error, "Consumer Partition Error") + } + ts := e.Timestamp.UnixNano()/ 1e6 + consumer.messageHandler(decodeKey(e.Key), e.Value, &types.Meta{ + Topic: *(e.TopicPartition.Topic), + ID: uint64(e.TopicPartition.Offset), + Timestamp: ts, + }) + consumer.lastKafkaEventTs = ts + case kafka.AssignedPartitions: + logPartitions("Kafka Consumer: Partitions Assigned", e.Partitions) + consumer.partitions = e.Partitions + consumer.c.Assign(e.Partitions) + case kafka.RevokedPartitions: + log.Println("Kafka Cosumer: Partitions Revoked") + consumer.partitions = nil + consumer.c.Unassign() + case kafka.Error: + if e.Code() == kafka.ErrAllBrokersDown { + os.Exit(1) + } + log.Printf("Consumer error: %v\n", e) + } + return nil +} + +func (consumer *Consumer) Close() { + if consumer.commitTicker != nil { + consumer.Commit() + } + if err := consumer.c.Close(); err != nil { + log.Printf("Kafka consumer close error: %v", err) + } +} + + + +// func (consumer *Consumer) consume( +// message func(m *kafka.Message) error, +// commit func(c *kafka.Consumer) error, +// ) error { +// if err := consumer.c.Subscribe(consumer.topic, nil); err != nil { +// return err +// } +// defer consumer.close() +// sigchan := make(chan os.Signal, 1) +// signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) +// ticker := time.NewTicker(consumer.commitInterval) +// defer ticker.Stop() +// for { +// select { +// case <-sigchan: +// return commit(consumer.c) +// case <-ticker.C: +// if err := commit(consumer.c); err != nil { +// return err +// } +// default: +// ev := consumer.c.Poll(consumer.pollTimeout) +// if ev == nil { +// continue +// } +// switch e := ev.(type) { +// case *kafka.Message: +// if e.TopicPartition.Error != nil { +// log.Println(e.TopicPartition.Error) +// continue +// } +// if err := message(e); err != nil { +// return err +// } +// case kafka.AssignedPartitions: +// if err := consumer.c.Assign(e.Partitions); err != nil { +// return err +// } +// case kafka.RevokedPartitions: +// if err := commit(consumer.c); err != nil { +// return err +// } +// if err := consumer.c.Unassign(); err != nil { +// return err +// } +// case kafka.Error: +// log.Println(e) +// if e.Code() == kafka.ErrAllBrokersDown { +// return e +// } +// } +// } +// } +// } + + +// func (consumer *Consumer) Consume( +// message func(key uint64, value []byte) error, +// ) error { +// return consumer.consume( +// func(m *kafka.Message) error { +// return message(decodeKey(m.Key), m.Value) +// }, +// func(c *kafka.Consumer) error { +// if _, err := c.Commit(); err != nil { +// log.Println(err) +// } +// return nil +// }, +// ) +// } + +// func (consumer *Consumer) ConsumeWithCommitHook( +// message func(key uint64, value []byte) error, +// commit func() error, +// ) error { +// return consumer.consume( +// func(m *kafka.Message) error { +// return message(decodeKey(m.Key), m.Value) +// }, +// func(c *kafka.Consumer) error { +// if err := commit(); err != nil { +// return err +// } +// if _, err := c.Commit(); err != nil { +// log.Println(err) +// } +// return nil +// }, +// ) +// } diff --git a/ee/backend/pkg/kafka/key.go b/ee/backend/pkg/kafka/key.go new file mode 100644 index 000000000..5106df722 --- /dev/null +++ b/ee/backend/pkg/kafka/key.go @@ -0,0 +1,20 @@ +package kafka + +import "encoding/binary" + +const PARTITIONS_EXPONENT = 3 +const PARTITIONS_MAX_INDEX uint64 = 1<