Agent skill

Metrics Pipeline

by OpenLitterMap in OpenLitterMap/openlittermap-web

MetricsService, RedisMetricsCollector, ProcessPhotoMetrics, metrics table, Redis stats, leaderboards, XP processing, and photo processing state (processedat/fp/tags/xp).

GPL-3.0Auto-check passedDatabases

Install Metrics Pipeline

skills CLI
$ npx skills add OpenLitterMap/openlittermap-web --skill metrics-pipeline -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install OpenLitterMap/openlittermap-web metrics-pipeline --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/OpenLitterMap/openlittermap-web.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.ai/skills/metrics-pipeline .claude/skills/metrics-pipeline && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
metrics-pipeline
GitHub stars
134
Token cost
~1.8k tokens
SKILL.md length
501 words
Files
1
Skills in repo
16
Repo updated
First seen
Licence
GPL-3.0

At a glance

MetricsService, RedisMetricsCollector, ProcessPhotoMetrics, metrics table, Redis stats, leaderboards, XP processing, and photo processing state (processedat/fp/tags/xp).

  • Works in 8 steps: Single writer rule. Only MetricsService… → Processing state is four columns:… → Fingerprint-based idempotency.… → …
  • Databases work in your project
  • SKILL.md covers Key Files, Invariants, Patterns and Common Mistakes
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Metrics Pipeline is an agent skill from OpenLitterMap/openlittermap-web. MetricsService, RedisMetricsCollector, ProcessPhotoMetrics, metrics table, Redis stats, leaderboards, XP processing, and photo processing state (processedat/fp/tags/xp).

Its SKILL.md is about 1.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Databases. It works with Redis, MySQL and PHP. The repository describes itself as: https://opengeospatialdata.springeropen.com/articles/10.1186/s40965-018-0050-y. The licence is GPL-3.0.

When your agent uses it

  • Databases work in your project

Example prompts

  • “/metrics-pipeline”

Workflow steps

8 steps, taken from the first numbered list in SKILL.md.

  1. Single writer rule. Only MetricsService writes to the metrics table and Redis metric keys. No other code may increment/decrement counters.
  2. Processing state is four columns: processed_at, processed_fp, processed_tags, processed_xp. A photo with processed_at = null has never…
  3. Fingerprint-based idempotency. MetricsService diffs old processed_tags JSON against new summary and writes only non-zero deltas. Safe to…
  4. Summary must exist before metrics fire. GeneratePhotoSummaryService::run() MUST be called before TagsVerifiedByAdmin dispatches…
  5. Redis is a derived cache. Rebuildable from the metrics table. RedisKeys::* is single source of truth for key naming.
  6. processed_xp must be INT UNSIGNED, not TINYINT. Overflow bug documented in migration 2026_02_23_182605.
  7. Tags count excludes categories to avoid double-counting: tags_count = objects + materials + brands + custom_tags.
  8. ProcessPhotoMetrics logs a warning when photo not found. If a photo is soft-deleted before the queued listener runs…

What it can do on your machine

Read from SKILL.md and the folder at commit ac688aa. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are php).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Metrics Pipeline loads about 1.8k tokens when it runs. Until then it costs about 47 tokens; SKILL.md has 501 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~47
When it runs · the whole SKILL.md, loaded when a task matches
~1.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from OpenLitterMap/openlittermap-web at commit ac688aa, republished under its GPL-3.0 licence (© OpenLitterMap). 501 words, ~1,781 tokens.

Download SKILL.mdSave it as .claude/skills/metrics-pipeline/SKILL.md (or your agent's skills folder).
name
metrics-pipeline
description
MetricsService, RedisMetricsCollector, ProcessPhotoMetrics, metrics table, Redis stats, leaderboards, XP processing, and photo processing state (processed_at/fp/tags/xp).

Metrics Pipeline

MetricsService is the single writer for all metrics — MySQL time-series and Redis aggregates. Nothing else touches metric counters. This is the golden rule.

Key Files

  • app/Services/Metrics/MetricsService.php — Single writer for MySQL + Redis
  • app/Services/Redis/RedisMetricsCollector.php — Redis operations (stats, HLL, rankings, tags)
  • app/Services/Redis/RedisKeys.php — All Redis key builders (single source of truth for naming)
  • app/Listeners/Metrics/ProcessPhotoMetrics.php — Queued listener on TagsVerifiedByAdmin
  • app/Events/TagsVerifiedByAdmin.php — Trigger event for metrics processing
  • app/Enums/LocationType.php — Global(0), Country(1), State(2), City(3) with scope prefixes

Invariants

  1. Single writer rule. Only MetricsService writes to the metrics table and Redis metric keys. No other code may increment/decrement counters.
  2. Processing state is four columns: processed_at, processed_fp, processed_tags, processed_xp. A photo with processed_at = null has never affected aggregates.
  3. Fingerprint-based idempotency. MetricsService diffs old processed_tags JSON against new summary and writes only non-zero deltas. Safe to call repeatedly on any photo.
  4. Summary must exist before metrics fire. GeneratePhotoSummaryService::run() MUST be called before TagsVerifiedByAdmin dispatches. MetricsService reads from photo.summary.
  5. Redis is a derived cache. Rebuildable from the metrics table. RedisKeys::* is single source of truth for key naming.
  6. processed_xp must be INT UNSIGNED, not TINYINT. Overflow bug documented in migration 2026_02_23_182605.
  7. Tags count excludes categories to avoid double-counting: tags_count = objects + materials + brands + custom_tags.
  8. ProcessPhotoMetrics logs a warning when photo not found. If a photo is soft-deleted before the queued listener runs, ProcessPhotoMetrics::handle() logs a warning and returns gracefully. It does NOT throw or retry.

Patterns

How MetricsService processes a photo
php
// MetricsService::processPhoto() — called by ProcessPhotoMetrics listener
DB::transaction(function () use ($photo) {
    $photo = Photo::whereKey($photo->id)->lockForUpdate()->first();
    $metrics = $this->extractMetricsFromPhoto($photo);  // reads photo.summary
    $fingerprint = $this->computeFingerprint($metrics['tags']);

    // Skip if nothing changed (fingerprint + XP both match)
    if ($photo->processed_fp === $fingerprint &&
        (int)$photo->processed_xp === (int)$metrics['xp']) {
        return;
    }

    // Route to create (first time) or update (re-tag)
    if ($photo->processed_at !== null) {
        $this->doUpdate($photo, $metrics, $fingerprint);
    } else {
        $this->doCreate($photo, $metrics, $fingerprint);
    }
});
MySQL upsert across timescales and locations

Each photo writes up to 40 rows: 5 timescales (all-time, daily, weekly, monthly, yearly) x 4 location scopes (global, country, state, city) x 2 (aggregate user_id=0 + per-user user_id>0).

php
DB::table('metrics')->upsert($rows,
    ['timescale', 'location_type', 'location_id', 'user_id', 'year', 'month', 'week', 'bucket_date'],
    [
        'uploads' => DB::raw('GREATEST(uploads + VALUES(uploads), 0)'),
        'tags'    => DB::raw('GREATEST(tags + VALUES(tags), 0)'),
        // ... same for brands, materials, custom_tags, litter, xp
    ]
);

Uploads delta: +1 for create, 0 for update, -1 for delete. GREATEST(..., 0) prevents negative counters.

Redis operations happen after MySQL commit
php
private function updateRedis(Photo $photo, array $payload, string $operation): void
{
    DB::afterCommit(function () use ($photo, $payload, $operation) {
        RedisMetricsCollector::processPhoto($photo, $payload, $operation);
    });
}
Redis key patterns (cluster-safe with hash tags)
php
RedisKeys::global()           // {g}
RedisKeys::country($id)       // {c:$id}
RedisKeys::state($id)         // {s:$id}
RedisKeys::city($id)          // {ci:$id}
RedisKeys::user($userId)      // {u:$userId}

RedisKeys::stats($scope)             // $scope:stats (HASH: uploads, tags, litter, xp, ...)
RedisKeys::hll($scope)               // $scope:hll (HyperLogLog for contributor count)
RedisKeys::objects($scope)            // $scope:obj (HASH: object_id => count)
RedisKeys::ranking($scope, $dim)      // $scope:rank:$dim (ZSET)
RedisKeys::xpRanking($scope)         // $scope:lb:xp (ZSET: user_id => xp, for leaderboards)
RedisKeys::userBitmap($userId)        // {u:$userId}:bitmap (activity bitmap)
Show full SKILL.md (201 more words)Show less
Where TagsVerifiedByAdmin fires
  1. Non-school users tag a photo: AddTagsToPhotoAction::updateVerification() — dispatches immediately after summary + XP (both web and mobile use this path).
  2. Teacher approves school photos: TeamPhotosController::approve() — dispatches per photo after atomic is_public = true update.
Delete flow (metrics reversal)
php
// MetricsService::deletePhoto() — called synchronously in controllers before soft-delete
// Reads processed_tags JSON, applies negative deltas, clears processed_* columns
$photo->update([
    'processed_at' => null,
    'processed_fp' => null,
    'processed_tags' => null,
    'processed_xp' => null,
]);

In Redis, the delete operation also prunes zero-XP members from leaderboard ZSETs:

php
$pipe->zIncrBy(RedisKeys::xpRanking($scope), -abs($metrics['xp']), (string)$userId);
$pipe->zRemRangeByScore(RedisKeys::xpRanking($scope), '-inf', '0');

This keeps Redis consistent with MySQL (which filters xp > 0).

Common Mistakes

  • Writing metrics outside MetricsService. Never DB::table('metrics')->increment(...) or Redis::hincrby(...) directly.
  • Dispatching TagsVerifiedByAdmin before summary generation. MetricsService reads photo.summary — null summary = zero metrics.
  • Comparing processed_xp as TINYINT. Values above 127 overflow. Column must be UNSIGNED INT.
  • Forgetting row locking. Always use Photo::whereKey($id)->lockForUpdate()->first() inside the transaction.
  • Assuming Redis is source of truth. Redis is a cache. The metrics table is authoritative.
  • Including categories in tags_count. Categories are groupings, not countable items. Only objects + materials + brands + custom_tags.
  • Not logging when ProcessPhotoMetrics can't find the photo. ProcessPhotoMetrics logs a warning (Log::warning(...)) when the photo is not found (soft-deleted or missing). It does not throw — the job completes successfully to avoid retries.
  • Using is_public as the upload metrics gate. UploadPhotoController gates recordUploadMetrics() on $team->isSchool(), NOT on $photo->is_public. Private-by-choice photos (non-school) still get immediate upload XP. Only school photos defer metrics to teacher approval.

© OpenLitterMap, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .ai/skills/metrics-pipeline of OpenLitterMap/openlittermap-web.

Open the folder on GitHubat commit ac688aa

Compare with similar skills

Metrics Pipeline next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Metrics Pipeline compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Metrics Pipeline this skillOpenLitterMap/openlittermap-web134—~1.8kAutomated safety check: PassGPL-3.0
Email Blastantiwork/gumroad9.8k—~1.4kAutomated safety check: PassMIT
Tgf Server Devthkhxm/tgf128—~1.3kAutomated safety check: NotesMIT
Alsacreations Guidelinesalsacreations/kiwipedia338—~900Automated safety check: PassNone
Cache Debugzhyese/grid-qa131—~646Automated safety check: PassCustom licence
Resume Backend Project OptimizerLAIJiangFeng/resume-builder248—~868Automated safety check: PassNone

Similar skills

  • Email Blast

    antiwork/gumroad

    Send one-off email blasts to Gumroad creators directly via production console, no PR or deploy needed.

    9.8k GitHub stars~1.4k tokensUpdated today
    DatabasesAuto-check passed
  • Tgf Server Dev

    thkhxm/tgf

    基于 tgf v2(github.com/thkhxm/tgf/v2)用确定性的 tgfctl 工作流创建、验证和维护 Go 游戏服务器项目。

    128 GitHub stars~1.3k tokensUpdated 2 mo ago
    DatabasesAuto-check: notes
  • Alsacreations Guidelines

    alsacreations/kiwipedia

    Guidelines techniques et conventions internes d'Alsacréations (Kiwipedia) — HTML, CSS, JavaScript, TypeScript, Vue.js, WordPress, PHP/MySQL, accessibilité, performance, SEO, RGPD, écoconception…

    338 GitHub stars~900 tokensUpdated 21 days ago
    DatabasesAuto-check passed
  • Cache Debug

    zhyese/grid-qa

    排查问答缓存问题(不命中/脏缓存/黑名单误拦/置信度过滤/多轮不缓存)时使用。覆盖三级缓存(Redis/MySQL/Semantic)+黑名单+置信度规则。

    131 GitHub stars~646 tokensUpdated 6 days ago
    DatabasesAuto-check passed
  • Resume Backend Project Optimizer

    LAIJiangFeng/resume-builder

    将中文后端项目经历改写为高质量、可面试追问、强数据化的简历要点。适用于用户提供“项目经历/主要工作/职责描述”后,要求按统一模板输出“负责xxx功能 + 关键技术细节组合 + 解决问题 + 数据化结果”的场景;适用于 Java 后端求职、简历优化、面试前项目复盘,且需要对齐面试高频考点(Java 集合与并发、MySQL、Redis、Spring、消息队列、系统设计等)时使用。

    248 GitHub stars~868 tokensUpdated 1 mo ago
    DatabasesAuto-check passed
  • Svc Database

    s0ld13rr/pentestcode

    Database RCE paths — UDF, xpcmdshell, COPY TO PROGRAM, Redis key write.

    828 GitHub stars~379 tokensUpdated 8 days ago
    DatabasesAuto-check passed

More from OpenLitterMap/openlittermap-web

All 16 skills in this repo
  • Tailwindcss Development

    OpenLitterMap/openlittermap-web

    Styles applications using Tailwind CSS v3 utilities. An agent skill from OpenLitterMap/openlittermap-web.

    134 GitHub stars~713 tokensUpdated 26 days ago
    Auto-check passed
  • Olm Architecture

    OpenLitterMap/openlittermap-web

    OpenLitterMap v5 architecture reference. An agent skill from OpenLitterMap/openlittermap-web.

    134 GitHub stars~5.2k tokensUpdated 26 days ago
    Auto-check passed
  • Achievements System

    OpenLitterMap/openlittermap-web

    AchievementEngine, AchievementRepository, milestone checkers, AchievementsSeeder, userachievements pivot, AchievementsController API, and achievement evaluation flow.

    134 GitHub stars~1.4k tokensUpdated 26 days ago
    Auto-check passed
  • Admin System

    OpenLitterMap/openlittermap-web

    AdminController, photo approval, tag editing, deletion, MetricsService integration, admin middleware, verification queue, and admin XP.

    134 GitHub stars~3.9k tokensUpdated 26 days ago
    Auto-check passed
  • API Endpoints

    OpenLitterMap/openlittermap-web

    REST API endpoints, route structure, auth guards, request/response contracts, error patterns, and the full API surface for web SPA and mobile clients.

    134 GitHub stars~4k tokensUpdated 26 days ago
    Auto-check passed
  • Clustering System

    OpenLitterMap/openlittermap-web

    ClusteringService, tile keys, dirty tiles/teams, clustering commands, ClusterController GeoJSON API, PhotoObserver dirty marking, and map cluster rendering.

    134 GitHub stars~2k tokensUpdated 26 days ago
    Auto-check passed

Works with

Categories

Questions about Metrics Pipeline

What does Metrics Pipeline do?

MetricsService, RedisMetricsCollector, ProcessPhotoMetrics, metrics table, Redis stats, leaderboards, XP processing, and photo processing state (processedat/fp/tags/xp). Metrics Pipeline is an agent skill from OpenLitterMap/openlittermap-web. MetricsService, RedisMetricsCollector, ProcessPhotoMetrics, metrics table, Redis stats, leaderboards, XP processing, and photo processing state (processedat/fp/tags/xp).

When should I use Metrics Pipeline?

Metrics Pipeline fits situations like: databases work in your project.

How do I install Metrics Pipeline in Claude Code?

Run `npx skills add OpenLitterMap/openlittermap-web --skill metrics-pipeline -a claude-code`. Or copy the skill folder (.ai/skills/metrics-pipeline in OpenLitterMap/openlittermap-web) into .claude/skills/metrics-pipeline in your project. Claude Code loads it when a task matches its description.

How do I install Metrics Pipeline in Codex?

Run `npx skills add OpenLitterMap/openlittermap-web --skill metrics-pipeline -a codex`. Or copy the skill folder (.ai/skills/metrics-pipeline in OpenLitterMap/openlittermap-web) into .agents/skills/metrics-pipeline in your project. Codex loads it when a task matches its description.

Can I use Metrics Pipeline in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add OpenLitterMap/openlittermap-web --skill metrics-pipeline -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/metrics-pipeline, .gemini/skills/metrics-pipeline, .github/skills/metrics-pipeline and .opencode/skills/metrics-pipeline in your project.

What does Metrics Pipeline need to run?

SKILL.md names no scripts, command-line tools or credentials: Metrics Pipeline is instructions for the agent only.

Does Metrics Pipeline access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Metrics Pipeline safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Metrics Pipeline use?

Metrics Pipeline is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Metrics Pipeline use?

About 1.8k tokens (SKILL.md is roughly 7.1k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Metrics Pipeline?

Skills that share tags, products or a category with Metrics Pipeline: Email Blast (antiwork/gumroad, 9.8k stars), Tgf Server Dev (thkhxm/tgf, 128 stars), Alsacreations Guidelines (alsacreations/kiwipedia, 338 stars) and Cache Debug (zhyese/grid-qa, 131 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Metrics Pipeline?

OpenLitterMap (a GitHub organization) maintains it in OpenLitterMap/openlittermap-web, which has 134 GitHub stars. The repository holds 16 skills in this directory. The repository was last updated on September 14, 2026.

Source: OpenLitterMap/openlittermap-web on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.