# Getting services usage and inactivity over time

**URL:** https://community.zeek.org/t/getting-services-usage-and-inactivity-over-time/7660
**Category:** Development
**Tags:** development
**Created:** [December 9, 2024, 7:25am UTC](https://community.zeek.org/t/getting-services-usage-and-inactivity-over-time/7660 "2024-12-09T07:25:25Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![doppelganger](https://avatars.discourse-cdn.com/v4/letter/d/8797f3/32.png) [@doppelganger](https://community.zeek.org/u/doppelganger)
#### Post date: [December 9, 2024, 7:25am UTC](https://community.zeek.org/t/getting-services-usage-and-inactivity-over-time/7660/1 "2024-12-09T07:25:25Z")

</div>

I am developing an asset management app, in the backend I am using zeek for passive asset and services discovery.  
In my front side I have some dashboards for gathered data to visualize data better for users.  
On the frontend I have two visuals with these titles:

- Inactive services over time (Counting inactive services which were not used in period of time )
- Services usage frequency (Counting service usage base on request to that specific service )

To filling these visuals I am building a zeek custom script to get neccessary data to feed them since parsing conn.log might be tricky and needs heavier load on my back end.  
I have some errors in my script and I am no expert in zeek scripting so any info helps me alot  
Here is my zeek script:

```auto

@load base/frameworks/cluster

module ServiceMonitor;

export {
    ## Configuration for monitored services
    redef enum Log::ID += { LOG_ServiceMonitor };

    ## Table to hold service usage stats
    global service_usage: table[addr, port] of record(
        connection_count: count,
        last_seen: time
    ) &default=[0, 0 secs];
}

event zeek_init() {
    # Set up log for tracking
    Log::create_stream(Log::LOG_ServiceMonitor, [$columns=Info, $path="service_monitor"]);

    print "Service Monitor script initialized.";
}

event connection_established(c: connection) {
    local dst = c$id$resp_h;
    local dport = c$id$resp_p;

    # Only monitor connections to local services
    if (Site::is_local_addr(dst)) {
        # Update the service usage stats
        service_usage[dst, dport]$connection_count += 1;
        service_usage[dst, dport]$last_seen = network_time;

        # Log connection activity
        Log::write(Log::LOG_ServiceMonitor, [$ts=network_time, $src_ip=c$id$orig_h, $dst_ip=dst, $dst_port=dport, $count=service_usage[dst, dport]$connection_count]);
    }
}

event timer(t: time) {
    # Check for inactive services periodically (e.g., every 60 seconds)
    local threshold = 300 secs; # 5 minutes inactivity threshold

    for (service in service_usage) {
        local last_seen = service_usage[service]$last_seen;
        if (network_time - last_seen > threshold) {
            print fmt("Service %s:%d is inactive for %d seconds", service[0], service[1], network_time - last_seen);
        }
    }
}

# Periodic execution of timer event
event zeek_done() {
    schedule 60 secs { timer(network_time); };
}

```

I tried to check syntax with ‘zeek -C script.zeek’ command and I am getting some errors  
Can anyone check and revise my script to help??

---

<div class="post-metadata">

### Author: ![Benjamin\_Bannier](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/benjamin_bannier/32/595_2.png) [@Benjamin\_Bannier](https://community.zeek.org/u/Benjamin_Bannier)
#### Post date: [December 9, 2024, 1:23pm UTC](https://community.zeek.org/t/getting-services-usage-and-inactivity-over-time/7660/2 "2024-12-09T13:23:55Z")

</div>

> [@doppelganger](#):
>
> I tried to check syntax with ‘zeek -C script.zeek’ command and I am getting some errors

Mentioning what kind of errors you were getting would have been useful (syntax errors in the script, or errors at runtime). Looking at your script I suspect syntax errors.

A couple of things:

- The `table .. of record` syntax does not exist. You need to declare an explicit `record` somewhere. To set `&default` you need to use proper record initialization syntax.
- `LOG_ServiceMonitor` does not live in the `Log` module, but instead the current module; you can directly use it.
- The `Info` record is never declared. If you did declare it you cannot name a field `count` which is a type, not an identifier.
- `network_time` is a function not a value, you need to invoke it.
- Your table iteration `for (service in service_usage) {` binds the individual values in the table to `service`, so you cannot use it like you did. I’d suggest you directly get the the keys as well with `for ([host, p], service in service_usage) {` and rework the indexing into `service_usage`.
- `schedule` expects an expression, not a statement.
- I am not sure your scheduling approach works like you intended.

If you used a text generator to create parts or all of this code please consider spending some time to understand well-isolated pieces yourself next time. This frees up both you and us from spending time on the wrong problems.
