@@ -10,9 +10,6 @@ resource.tracer.maxbackups: 5
1010resource.tracer.maxsize: 5
1111{{ /if }}
1212
13- regexp:
14- "next_offset_timestamp": '^\d+'
15-
1613state:
1714 url:{{ hostname }}
1815 integration_key:{{ integration_key }}
@@ -31,113 +28,112 @@ program: |
3128 state
3229 :
3330 state.with({
34- "mintime": state.?cursor.last_published.orValue(int(now - duration(state.initial_interval)) * 1000),
35- "maxtime": int(now - duration("2m")) * 1000,
36- "date": now.format(time_layout.RFC1123Z),
31+ "mintime": string(int(state.?cursor.last_published.orValue(int(now - duration(state.initial_interval)) * 1000))),
3732 })
38- ).as(state, state.with(
39- request(
40- "GET",
41- state.?want_more.orValue(false) ?
42- state.next_url
43- :
44- state.url.trim_right("/") + "/admin/v2/logs/activity?" + {
45- "limit": [string(int(state.limit))],
46- "maxtime": [string(int(state.maxtime))],
47- "mintime": [string(int(state.mintime))],
48- "sort": ["ts:asc"],
49- }.format_query()
50- ).with(
51- {
33+ ).as(state, state.with({
34+ // the duration between maxtime and mintime should be less than 180d to avoid error_code 400 from API.
35+ "maxtime": state.want_more ?
36+ string(state.maxtime)
37+ :
38+ string(int([
39+ int(timestamp(int(state.mintime)/1000) + duration("4320h")),
40+ int(now - duration("2m"))
41+ ].min()) * 1000)
42+ })).as(state, state.with(
43+ // prepare request data
44+ {
45+ // data should be calculated for each request to avoid error 40103
46+ "date": now.format(time_layout.RFC1123Z),
47+ "method": "GET",
48+ "url_base": state.url.trim_right("/"),
49+ "url_path": "/admin/v2/logs/activity",
50+ "query_string": {
51+ "limit": [string(dyn(state).limit)],
52+ "maxtime": [string(state.maxtime)],
53+ "mintime": [string(state.mintime)],
54+ ?"next_offset": state.?next_offset.optMap(v, [string(v)]),
55+ "sort": ["ts:asc"],
56+ }.format_query(),
57+ }.as(r, r.with({
58+ // add an authorization header value
59+ "authorization": "Basic " + (
60+ state.integration_key + ":" + (
61+ [
62+ r.date,
63+ r.method,
64+ r.url_base.trim_prefix("https://"),
65+ r.url_path,
66+ r.query_string,
67+ ].join("\n")
68+ .hmac("sha1", bytes(state.secret_key))
69+ .hex()
70+ )
71+ ).base64(),
72+ })).as(r,
73+ // do the request using the prepared data
74+ request(
75+ r.method,
76+ [r.url_base, r.url_path, "?", r.query_string].join("")
77+ ).with({
5278 "Header": {
5379 "Content-Type": ["application/x-www-form-urlencoded"],
54- "Date": [state.date],
55- "Authorization": ["Basic " + (
56- state.integration_key + ":" + (
57- [
58- state.date,
59- "GET",
60- state.url.trim_prefix("https://"),
61- "/admin/v2/logs/activity",
62- {
63- "limit": [string(int(state.limit))],
64- "maxtime": [string(int(state.maxtime))],
65- "mintime": [string(int(state.mintime))],
66- ?"next_offset": has(state.next_offset) ?
67- optional.of([string(state.next_offset)])
68- :
69- optional.none(),
70- "sort": ["ts:asc"],
71- }.format_query()
72- ].join("\n")
73- .hmac("sha1", bytes(state.secret_key))
74- .hex()
75- )
76- ).base64()],
80+ "Date": [r.date],
81+ "Authorization": [r.authorization],
7782 },
78- }
79- ).do_request().as(resp, (resp.StatusCode == 200) ?
80- bytes(resp.Body).decode_json().as(body, has(body.?response.items)&& size(body.response.items) > 0 ?
81- {
82- "events": body.response.items.map(item,
83- {
84- "message": item.encode_json(),
85- }
86- ),
87- "url": state.url,
88- "integration_key": state.integration_key,
89- "secret_key": state.secret_key,
90- "limit": state.limit,
91- "mintime": state.mintime,
92- "maxtime": state.maxtime,
93- "want_more": has(body.?response.?metadata.next_offset),
94- ?"next_offset": (body.?response.metadata.next_offset.orValue(null) != null) ?
95- optional.of(string(body.response.metadata.next_offset))
96- :
97- optional.none(),
98- "next_url": (body.?response.metadata.next_offset.orValue(null) != null) ?
99- (
100- state.url.trim_right("/") + "/admin/v2/logs/activity?" + {
101- "limit": [string(int(state.limit))],
102- "maxtime": [string(int(state.maxtime))],
103- "mintime": [string(int(state.mintime))],
104- "next_offset": [string(body.response.metadata.next_offset)],
105- "sort": ["ts:asc"],
106- }.format_query()
107- )
108- :
109- state.url,
110- "cursor": {
111- ?"last_published": (body.?response.metadata.next_offset.orValue(null) != null) ?
112- optional.of(body.response.metadata.next_offset.re_find("next_offset_timestamp"))
83+ }).do_request().as(resp, (resp.StatusCode == 200) ?
84+ bytes(resp.Body).decode_json().as(body, has(body.?response.items)&& size(body.response.items) > 0 ?
85+ {
86+ "events": body.response.items.map(item,
87+ {
88+ "message": item.encode_json(),
89+ }
90+ ),
91+ "want_more": has(body.?response.metadata.next_offset),
92+ ?"next_offset": (body.?response.metadata.next_offset.orValue(null) != null) ?
93+ optional.of(string(body.response.metadata.next_offset))
11394 :
11495 optional.none(),
96+ "cursor": {
97+ ?"last_published": (has(body.?response.items)&& size(body.response.items) > 0) ?
98+ optional.of(
99+ body.response.items.map(i, i.ts).max().as(last_timestamp,
100+ !has(dyn(state).?cursor.last_published) ?
101+ last_timestamp
102+ : (last_timestamp< dyn(state).cursor.last_published) ?
103+ dyn(state).cursor.last_published
104+ :
105+ last_timestamp
106+ )
107+ )
108+ :
109+ dyn(state).?cursor.last_published,
110+ }
111+ }
112+ :
113+ {
114+ "events":[],
115+ "want_more": false,
115116 }
116- }
117- :
118- {
119- "events":[],
120- "want_more": false,
121- }
122117
123- )
124- :
125- bytes(resp.Body).decode_json().as(body,
126- {
127- "events": {
128- "error": {
129- "code": has(body.code) ? string(body.code) : string(resp.StatusCode),
130- "id": string(resp.Status),
131- "message": "GET:"+(
132- size(resp.Body) != 0 ?
133- string(resp.Body)
134- :
135- string(resp.Status) + ' (' + string(resp.StatusCode) + ')'
136- ),
118+ )
119+ :
120+ bytes(resp.Body).decode_json().as(body,
121+ {
122+ "events": {
123+ "error": {
124+ "code": has(body.code) ? string(body.code) : string(resp.StatusCode),
125+ "id": string(resp.Status),
126+ "message": "GET:"+(
127+ size(resp.Body) != 0 ?
128+ string(resp.Body)
129+ :
130+ string(resp.Status) + ' (' + string(resp.StatusCode) + ')'
131+ ),
132+ },
137133 },
138- } ,
139- "want_more": false,
140- }
134+ "want_more": false ,
135+ }
136+ )
141137 )
142138 )
143139 ))