[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EFDXG01WS5A2D1W1AMW4S8":3,"skill-same:01M6EFDXG01WS5A2D1W1AMW4S8":45},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":20,"frontMatter":21,"refName":22,"commitSha":23,"skillDirectory":24,"forksCount":25,"repositoryHtmlUrl":26,"repositoryHomepageUrl":27,"ownerHtmlUrl":28,"ownerBlogUrl":6,"ownerDescription":29,"updatedAt":30,"install":31,"resources":44},"01M6EFDXG01WS5A2D1W1AMW4S8","loki",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Floki\u002FSKILL.md",[],[5],"2026-11-10 10:12:30",false,"# Loki\n\nLoki is a log aggregation system designed to be cost-effective and easy to operate. It takes a fundamentally different approach from Elasticsearch or Splunk: instead of indexing log content, it indexes only the labels attached to log streams. The actual log lines are compressed and stored in chunks. This means writes are fast, storage is cheap, and you still get powerful querying through LogQL.\n\nThis skill covers deploying Loki and Promtail with Docker, writing LogQL queries, and integrating Loki with Grafana for log exploration and alerting.\n\n## Docker Deployment\n\nA typical Loki setup has two components: the Loki server that stores and queries logs, and Promtail, an agent that ships logs from your hosts into Loki.\n\n```yaml\n# docker-compose.yml — Loki and Promtail deployment\n# Loki on port 3100, Promtail tails container logs via Docker socket\n\nversion: \"3.8\"\n\nservices:\n  loki:\n    image: grafana\u002Floki:latest\n    ports:\n      - \"3100:3100\"\n    volumes:\n      - .\u002Floki-config.yml:\u002Fetc\u002Floki\u002Flocal-config.yaml\n      - loki-data:\u002Floki\n    command: -config.file=\u002Fetc\u002Floki\u002Flocal-config.yaml\n\n  promtail:\n    image: grafana\u002Fpromtail:latest\n    volumes:\n      - .\u002Fpromtail-config.yml:\u002Fetc\u002Fpromtail\u002Fconfig.yml\n      - \u002Fvar\u002Flog:\u002Fvar\u002Flog:ro\n      - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock:ro\n    command: -config.file=\u002Fetc\u002Fpromtail\u002Fconfig.yml\n    depends_on:\n      - loki\n\nvolumes:\n  loki-data:\n```\n\n### Loki Configuration\n\n```yaml\n# loki-config.yml — minimal Loki server configuration\n# Single-instance mode with filesystem storage and 30-day retention\n\nauth_enabled: false\n\nserver:\n  http_listen_port: 3100\n\ncommon:\n  ring:\n    instance_addr: 127.0.0.1\n    kvstore:\n      store: inmemory\n  replication_factor: 1\n  path_prefix: \u002Floki\n\nschema_config:\n  configs:\n    - from: \"2024-01-01\"\n      store: tsdb\n      object_store: filesystem\n      schema: v13\n      index:\n        prefix: index_\n        period: 24h\n\nstorage_config:\n  filesystem:\n    directory: \u002Floki\u002Fchunks\n\nlimits_config:\n  retention_period: 720h\n  max_query_series: 5000\n\ncompactor:\n  working_directory: \u002Floki\u002Fcompactor\n  retention_enabled: true\n```\n\n## Promtail Agent\n\nPromtail discovers log targets, attaches labels, and pushes log entries to Loki. It can tail files, scrape journal entries, and read Docker container logs.\n\n```yaml\n# promtail-config.yml — Promtail agent configuration\n# Scrapes Docker container logs and labels them with container name and compose service\n\nserver:\n  http_listen_port: 9080\n\npositions:\n  filename: \u002Ftmp\u002Fpositions.yaml\n\nclients:\n  - url: http:\u002F\u002Floki:3100\u002Floki\u002Fapi\u002Fv1\u002Fpush\n\nscrape_configs:\n  - job_name: docker\n    docker_sd_configs:\n      - host: unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock\n        refresh_interval: 5s\n    relabel_configs:\n      - source_labels: ['__meta_docker_container_name']\n        target_label: container\n        regex: '\u002F(.+)'\n      - source_labels: ['__meta_docker_container_label_com_docker_compose_service']\n        target_label: service\n\n  - job_name: system\n    static_configs:\n      - targets: [localhost]\n        labels:\n          job: syslog\n          host: production-1\n          __path__: \u002Fvar\u002Flog\u002Fsyslog\n```\n\n### Structured Metadata with Pipeline Stages\n\nPromtail can parse log lines and extract labels or structured metadata using pipeline stages:\n\n```yaml\n# promtail-pipeline.yml — pipeline stages for JSON log parsing\n# Extracts level, method, and status from JSON application logs\n\nscrape_configs:\n  - job_name: app\n    static_configs:\n      - targets: [localhost]\n        labels:\n          job: myapp\n          __path__: \u002Fvar\u002Flog\u002Fmyapp\u002F*.log\n    pipeline_stages:\n      - json:\n          expressions:\n            level: level\n            method: method\n            status: status\n            duration: duration_ms\n      - labels:\n          level:\n      - timestamp:\n          source: timestamp\n          format: RFC3339\n```\n\n## LogQL Queries\n\nLogQL is Loki's query language. It starts with a log stream selector (labels in curly braces) and optionally chains filter expressions and aggregations.\n\n### Stream Selection and Filtering\n\n```logql\n# LogQL — all logs from the API service\n{service=\"api\"}\n```\n\n```logql\n# LogQL — API errors containing \"timeout\"\n{service=\"api\"} |= \"timeout\" | logfmt | level=\"error\"\n```\n\n```logql\n# LogQL — filter with regex, exclude health checks\n{service=\"api\"} |~ \"POST|PUT\" !~ \"\u002Fhealthz\"\n```\n\n### Parsing and Extracting Fields\n\n```logql\n# LogQL — parse JSON logs and filter by HTTP status\n{service=\"api\"} | json | status >= 500\n```\n\n```logql\n# LogQL — parse logfmt and extract specific fields\n{job=\"myapp\"} | logfmt | duration > 1000 | line_format \"slow request: {{.method}} {{.path}} took {{.duration}}ms\"\n```\n\n### Metric Queries\n\nLogQL can compute metrics from logs, turning log data into time-series:\n\n```logql\n# LogQL — error rate per service over 5-minute windows\nsum by (service) (rate({job=\"myapp\"} |= \"error\" [5m]))\n```\n\n```logql\n# LogQL — 99th percentile request duration from parsed logs\nquantile_over_time(0.99, {service=\"api\"} | json | unwrap duration_ms [5m]) by (method)\n```\n\n```logql\n# LogQL — top 5 noisiest log sources by volume\ntopk(5, sum by (service) (rate({job=~\".+\"} [1h])))\n```\n\n## Grafana Integration\n\nLoki is a first-class data source in Grafana. Adding it lets you view logs alongside metrics on the same dashboard, which is essential for correlating issues.\n\n### Provisioning Loki as a Data Source\n\n```yaml\n# provisioning\u002Fdatasources\u002Floki.yml — Loki data source for Grafana\napiVersion: 1\n\ndatasources:\n  - name: Loki\n    type: loki\n    access: proxy\n    url: http:\u002F\u002Floki:3100\n    jsonData:\n      maxLines: 1000\n      derivedFields:\n        - name: TraceID\n          matcherRegex: '\"trace_id\":\"(\\w+)\"'\n          url: 'http:\u002F\u002Ftempo:3200\u002Fapi\u002Ftraces\u002F${__value.raw}'\n          datasourceUid: tempo\n```\n\nThe `derivedFields` configuration extracts trace IDs from log lines and creates clickable links to a tracing backend, connecting logs to traces with zero effort.\n\n### Log Panel in a Dashboard\n\n```json\n{\n  \"__comment\": \"dashboard-panel.json — Grafana log panel showing API errors\",\n  \"type\": \"logs\",\n  \"title\": \"API Errors\",\n  \"gridPos\": { \"h\": 10, \"w\": 24, \"x\": 0, \"y\": 0 },\n  \"datasource\": { \"type\": \"loki\", \"uid\": \"loki\" },\n  \"targets\": [\n    {\n      \"expr\": \"{service=\\\"api\\\"} | json | level=\\\"error\\\"\",\n      \"refId\": \"A\"\n    }\n  ],\n  \"options\": {\n    \"showTime\": true,\n    \"showLabels\": true,\n    \"wrapLogMessage\": true,\n    \"sortOrder\": \"Descending\",\n    \"enableLogDetails\": true\n  }\n}\n```\n\n### Log-Based Alerts\n\nYou can create Grafana alert rules that fire when log patterns exceed a threshold:\n\n```yaml\n# provisioning\u002Falerting\u002Flog-alerts.yml — alert on high error log volume\napiVersion: 1\n\ngroups:\n  - orgId: 1\n    name: log-alerts\n    folder: Logs\n    interval: 60s\n    rules:\n      - uid: high-error-logs\n        title: High Error Log Volume\n        condition: A\n        data:\n          - refId: A\n            datasourceUid: loki\n            model:\n              expr: 'sum(rate({service=\"api\"} |= \"error\" [5m]))'\n              conditions:\n                - evaluator:\n                    type: gt\n                    params: [10]\n        for: 5m\n        labels:\n          severity: warning\n        annotations:\n          summary: \"Error log rate exceeds 10\u002Fs for the API service\"\n```\n\nLoki works best when you keep label cardinality low. Use labels for broad categories like service, environment, and host — not for high-cardinality values like user IDs or request IDs. Those belong in the log line itself, where LogQL can parse them on demand.\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Floki",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill loki",{"tool":37,"command":38},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill loki",{"tool":40,"command":41},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill loki","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Floki\u002FSKILL.md",true,[],[46,60,70,79,85,92],{"skillNo":47,"name":48,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":49,"categories":50,"keywords":56,"publishedAt":18},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[51],{"categoryNo":52,"categoryName":53,"taxonomyType":54,"taxonomyTypeDesc":55},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[57,58,59],"model","model hierarchy","model hierarchy skill",{"skillNo":61,"name":62,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":66,"publishedAt":18},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[65],{"categoryNo":52,"categoryName":53,"taxonomyType":54,"taxonomyTypeDesc":55},[67,68,69],"MCP","zoom","zoom mcp",{"skillNo":71,"name":72,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":18},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[76,77,78,68],"sdk","zoom apps sdk","apps",{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":84,"publishedAt":18},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[81],{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":91,"publishedAt":18},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[90],{"categoryNo":52,"categoryName":53,"taxonomyType":54,"taxonomyTypeDesc":55},[87],{"skillNo":93,"name":94,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":18},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[94]]