24 Hour Stats avatar

24 Hour Stats

Try for free

No credit card required

View all Actors
24 Hour Stats

24 Hour Stats

mtrunkat/24-hour-stats
Try for free

No credit card required

This act can be used as synchronous API. Returns a JSON containing actor runs finished in the last 24 hours along with information about their default datasets and request queues. Actors might be filtered via input array "actIds".

Dockerfile

1# This is a template for a Dockerfile used to run acts in Actor system.
2# The base image name below is set during the act build, based on user settings.
3# IMPORTANT: The base image must set a correct working directory, such as /usr/src/app or /home/user
4FROM apify/actor-node-basic:v0.21.10
5
6# Second, copy just package.json and package-lock.json since it should be
7# the only file that affects "npm install" in the next step, to speed up the build
8COPY package*.json ./
9
10# Install NPM packages, skip optional and development dependencies to
11# keep the image small. Avoid logging too much and print the dependency
12# tree for debugging
13RUN npm --quiet set progress=false \
14 && npm install --only=prod --no-optional \
15 && echo "Installed NPM packages:" \
16 && (npm list --all || true) \
17 && echo "Node.js version:" \
18 && node --version \
19 && echo "NPM version:" \
20 && npm --version
21
22# Copy source code to container
23# Do this in the last step, to have fast build if only the source code changed
24COPY  . ./
25
26# NOTE: The CMD is already defined by the base image.
27# Uncomment this for local node inspector debugging:
28# CMD [ "node", "--inspect=0.0.0.0:9229", "main.js" ]

package.json

1{
2    "name": "apify-project",
3    "version": "0.0.1",
4    "description": "",
5    "author": "It's not you it's me",
6    "license": "ISC",
7    "dependencies": {
8        "apify": "0.21.10",
9        "moment": "latest",
10        "bluebird": "latest",
11        "underscore": "latest"
12    },
13    "scripts": {
14        "start": "node main.js"
15    }
16}

main.js

1const Apify = require('apify');
2const moment = require('moment');
3const Promise = require('bluebird');
4const _ = require('underscore');
5
6
7const utils = require('apify-client/build/utils');
8const originalRequestPromise = utils.requestPromise;
9utils.requestPromise = (options, iteration = 0) => {
10    const startedAt = new Date();
11    //console.log(`${options.method} ${iteration} ${options.url} ${options.body ? options.body.url : 'null'}`);
12    return originalRequestPromise(options, iteration)
13        .then((response) => {
14            //console.log(JSON.stringify(response)); 
15            console.log(`${options.url} ${(Date.now() - startedAt) / 1000}`);
16            return response;
17        });
18};
19
20const MAX_OFFSET_LIMIT = 30000;
21const RUN_FIELDS = [
22    'id', 
23    'actId', 
24    'startedAt', 
25    'finishedAt', 
26    'status', 
27    'defaultDatasetId', 
28    'defaultRequestQueueId', 
29    'defaultKeyValueStoreId',
30];
31
32const getRunsFromPeriod = async (actId, from, to) => {
33    const runs = [];
34    let offset = 0;
35
36    while (true) {
37        let allFetched = true;
38        const response = await Apify.client.acts.listRuns({ actId, offset, desc: true });
39
40        response
41            .items
42            .filter(run => !run.finishedAt || run.finishedAt > from)
43            .forEach((run) => {
44                run.actId = actId;
45                runs.push(run);
46                allFetched = false;
47            });
48
49        offset += response.items.length;
50            
51        if (!response.items.length || allFetched || offset > MAX_OFFSET_LIMIT) return runs;
52    }
53};
54
55const fetchStorageObjects = async (ids, collection, listMethod) => {
56    const storages = {};
57    let offset = 0;
58
59    while (true) {
60        const response = await Apify.client[collection][listMethod]({ offset, desc: true, unnamed: true });
61
62        response.items.forEach((obj) => {
63            storages[obj.id] = obj;
64        });
65
66        offset += response.items.length;
67            
68        if (!response.items.length || _.size(storages) === ids.length || offset > MAX_OFFSET_LIMIT * 1.1) return storages;
69    }
70};
71
72Apify.main(async () => {
73    let input;
74    
75    try {
76        input = await Apify.getValue('INPUT');
77    } catch (err) {
78        // Swallow this, input is empty.
79    }
80
81    const to = new Date();
82    const from = moment(to).subtract(1, 'day').toDate();
83    const getRunsFromPeriodPartial = _.partial(getRunsFromPeriod, _, from, to);
84
85    const acts = (await Apify.client.acts.listActs())
86        .items
87        .filter((act) => {
88           if (!input || !input.actIds) return true;
89           
90           return input.actIds.includes(act.id);
91        });
92
93    const actNames = _.chain(acts).indexBy('id').mapObject(act => act.name).value();
94    const actIds = acts.map(act => act.id);
95    const runs = _.flatten(await Promise.mapSeries(actIds, getRunsFromPeriodPartial));
96    const datasetIds = _.pluck(runs, 'defaultDatasetId');
97    const queueIds = _.pluck(runs, 'defaultRequestQueueId');
98    const storeIds = _.pluck(runs, 'defaultKeyValueStoreId');
99
100    const queues = await fetchStorageObjects(storeIds, 'requestQueues', 'listQueues');
101    const datasets = await fetchStorageObjects(storeIds, 'datasets', 'listDatasets');
102
103    const actorRuns = runs
104        .map((run) => {
105            const dataset = datasets[run.defaultDatasetId];
106            const queue = queues[run.defaultRequestQueueId];
107            
108            return Object.assign(_.pick(run, ...RUN_FIELDS), {
109                actName: actNames[run.actId],
110                datasetItems: dataset ? dataset.itemCount : 'N/A',
111                requestQueueItems: queue ? queue.totalRequestCount : 'N/A',
112                requestQueuePending: queue ? queue.pendingRequestCount : 'N/A',
113                requestQueueHandled: queue ? queue.handledRequestCount : 'N/A',
114            });
115        });
116        
117    await Apify.setValue('OUTPUT', {
118        createdAt: to,
119        period: { from, to },
120        actorRuns,
121    });
122});
Developer
Maintained by Community

Actor Metrics

  • 1 monthly user

  • 2 stars

  • Created in Aug 2018

  • Modified 2 years ago

Categories