Loki/Promtail: Client Refactor (#3623)

* move docker driver

* move fluent-bit output plugin

* move fluentd plugin

* move logstash plugin

* move promtail

* match stage uses simple logql label matcher and filter expressions only

* remove remaining logql imports

* remove helpers package and move contents to util package

* move validation and runtime out of util package

* fix imports

* move build and cfg packages into util

* move ParseRequest function to util package

* create a new package for logql models and move marshal/unmarshal code to util folder

* move ErrorLabel to logqlmodel

* move stats package to logqlmodel

* decouple loghttp from logql by moving validation to logql package

* move gcplog to tools

* move PackedEntryKey constant to logqlmodel

* fix stats proto import and rebuild protos

* fix windows promtail tests

* update drone to new dockerfile locations
pull/3624/head
Ed Welch 4 years ago committed by GitHub
parent b04af08b1b
commit 6e67d1ea5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 63
      .drone/drone.jsonnet
  2. 267
      .drone/drone.yml
  3. 10
      .gitignore
  4. 66
      Makefile
  5. 4
      clients/cmd/docker-driver/Dockerfile
  6. 0
      clients/cmd/docker-driver/README.md
  7. 24
      clients/cmd/docker-driver/config.go
  8. 0
      clients/cmd/docker-driver/config.json
  9. 2
      clients/cmd/docker-driver/config_test.go
  10. 0
      clients/cmd/docker-driver/docker-compose.yaml
  11. 0
      clients/cmd/docker-driver/driver.go
  12. 0
      clients/cmd/docker-driver/http.go
  13. 7
      clients/cmd/docker-driver/loki.go
  14. 2
      clients/cmd/docker-driver/main.go
  15. 0
      clients/cmd/docker-driver/pipeline-example.yaml
  16. 4
      clients/cmd/fluent-bit/Dockerfile
  17. 0
      clients/cmd/fluent-bit/README.md
  18. 2
      clients/cmd/fluent-bit/buffer.go
  19. 2
      clients/cmd/fluent-bit/client.go
  20. 5
      clients/cmd/fluent-bit/config.go
  21. 3
      clients/cmd/fluent-bit/config_test.go
  22. 5
      clients/cmd/fluent-bit/dque.go
  23. 0
      clients/cmd/fluent-bit/fluent-bit.conf
  24. 5
      clients/cmd/fluent-bit/loki.go
  25. 5
      clients/cmd/fluent-bit/loki_test.go
  26. 5
      clients/cmd/fluent-bit/out_grafana_loki.go
  27. 0
      clients/cmd/fluentd/.gitignore
  28. 0
      clients/cmd/fluentd/.rspec
  29. 0
      clients/cmd/fluentd/.rubocop.yml
  30. 6
      clients/cmd/fluentd/Dockerfile
  31. 0
      clients/cmd/fluentd/Gemfile
  32. 0
      clients/cmd/fluentd/LICENSE
  33. 0
      clients/cmd/fluentd/README.md
  34. 0
      clients/cmd/fluentd/Rakefile
  35. 0
      clients/cmd/fluentd/bin/console
  36. 0
      clients/cmd/fluentd/bin/setup
  37. 0
      clients/cmd/fluentd/docker/Gemfile
  38. 0
      clients/cmd/fluentd/docker/conf/loki.conf
  39. 4
      clients/cmd/fluentd/docker/docker-compose.yml
  40. 0
      clients/cmd/fluentd/docker/fluent-bit.conf
  41. 0
      clients/cmd/fluentd/docker/fluentd.conf
  42. 0
      clients/cmd/fluentd/fluent-plugin-grafana-loki.gemspec
  43. 0
      clients/cmd/fluentd/lib/fluent/plugin/out_loki.rb
  44. 0
      clients/cmd/fluentd/spec/gems/fluent/plugin/data/syslog
  45. 0
      clients/cmd/fluentd/spec/gems/fluent/plugin/data/syslog2
  46. 0
      clients/cmd/fluentd/spec/gems/fluent/plugin/loki_output_spec.rb
  47. 0
      clients/cmd/fluentd/spec/spec_helper.rb
  48. 0
      clients/cmd/logstash/.gitignore
  49. 2
      clients/cmd/logstash/Dockerfile
  50. 0
      clients/cmd/logstash/Gemfile
  51. 0
      clients/cmd/logstash/README.md
  52. 0
      clients/cmd/logstash/Rakefile
  53. 0
      clients/cmd/logstash/lib/logstash/outputs/loki.rb
  54. 0
      clients/cmd/logstash/lib/logstash/outputs/loki/batch.rb
  55. 0
      clients/cmd/logstash/lib/logstash/outputs/loki/entry.rb
  56. 0
      clients/cmd/logstash/logstash-output-loki.gemspec
  57. 0
      clients/cmd/logstash/loki-test.conf
  58. 0
      clients/cmd/logstash/loki.conf
  59. 0
      clients/cmd/logstash/spec/outputs/loki/entry_spec.rb
  60. 0
      clients/cmd/logstash/spec/outputs/loki_spec.rb
  61. 4
      clients/cmd/promtail/Dockerfile
  62. 6
      clients/cmd/promtail/Dockerfile.arm32
  63. 8
      clients/cmd/promtail/Dockerfile.cross
  64. 8
      clients/cmd/promtail/Dockerfile.debug
  65. 11
      clients/cmd/promtail/main.go
  66. 0
      clients/cmd/promtail/promtail-docker-config.yaml
  67. 0
      clients/cmd/promtail/promtail-local-config.yaml
  68. 0
      clients/cmd/promtail/promtail-local-pubsub-config.yaml
  69. 0
      clients/cmd/promtail/promtail-windows.yaml
  70. 102
      clients/pkg/logentry/logql/ast.go
  71. 65
      clients/pkg/logentry/logql/expr.y
  72. 542
      clients/pkg/logentry/logql/expr.y.go
  73. 118
      clients/pkg/logentry/logql/parser.go
  74. 157
      clients/pkg/logentry/logql/parser_test.go
  75. 0
      clients/pkg/logentry/metric/counters.go
  76. 0
      clients/pkg/logentry/metric/counters_test.go
  77. 0
      clients/pkg/logentry/metric/gauges.go
  78. 0
      clients/pkg/logentry/metric/gauges_test.go
  79. 0
      clients/pkg/logentry/metric/histograms.go
  80. 0
      clients/pkg/logentry/metric/histograms_test.go
  81. 0
      clients/pkg/logentry/metric/metricvec.go
  82. 0
      clients/pkg/logentry/stages/drop.go
  83. 0
      clients/pkg/logentry/stages/drop_test.go
  84. 0
      clients/pkg/logentry/stages/extensions.go
  85. 0
      clients/pkg/logentry/stages/extensions_test.go
  86. 0
      clients/pkg/logentry/stages/json.go
  87. 0
      clients/pkg/logentry/stages/json_test.go
  88. 0
      clients/pkg/logentry/stages/labelallow.go
  89. 0
      clients/pkg/logentry/stages/labelallow_test.go
  90. 0
      clients/pkg/logentry/stages/labeldrop.go
  91. 0
      clients/pkg/logentry/stages/labeldrop_test.go
  92. 0
      clients/pkg/logentry/stages/labels.go
  93. 0
      clients/pkg/logentry/stages/labels_test.go
  94. 41
      clients/pkg/logentry/stages/match.go
  95. 0
      clients/pkg/logentry/stages/match_test.go
  96. 2
      clients/pkg/logentry/stages/metrics.go
  97. 2
      clients/pkg/logentry/stages/metrics_test.go
  98. 3
      clients/pkg/logentry/stages/multiline.go
  99. 3
      clients/pkg/logentry/stages/multiline_test.go
  100. 0
      clients/pkg/logentry/stages/output.go
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,4 +1,4 @@
local apps = ['loki', 'loki-canary', 'promtail', 'logcli'];
local apps = ['loki', 'loki-canary', 'logcli'];
local archs = ['amd64', 'arm64', 'arm'];
local build_image_version = std.extVar('__build-image-version');
@ -44,6 +44,18 @@ local docker(arch, app) = {
},
};
local clients_docker(arch, app) = {
name: '%s-image' % if $.settings.dry_run then 'build-' + app else 'publish-' + app,
image: 'plugins/docker',
settings: {
repo: 'grafana/%s' % app,
dockerfile: 'clients/cmd/%s/Dockerfile' % app,
username: { from_secret: 'docker_username' },
password: { from_secret: 'docker_password' },
dry_run: false,
},
};
local arch_image(arch, tags='') = {
platform: {
os: 'linux',
@ -70,7 +82,7 @@ local promtail_win() = pipeline('promtail-windows') {
name: 'test',
image: 'golang:windowsservercore-1809',
commands: [
'go test .\\pkg\\promtail\\targets\\windows\\... -v',
'go test .\\clients\\pkg\\promtail\\targets\\windows\\... -v',
],
}],
};
@ -78,7 +90,7 @@ local promtail_win() = pipeline('promtail-windows') {
local fluentbit() = pipeline('fluent-bit-amd64') + arch_image('amd64', 'latest,master') {
steps+: [
// dry run for everything that is not tag or master
docker('amd64', 'fluent-bit') {
clients_docker('amd64', 'fluent-bit') {
depends_on: ['image-tag'],
when: condition('exclude').tagMaster,
settings+: {
@ -88,7 +100,7 @@ local fluentbit() = pipeline('fluent-bit-amd64') + arch_image('amd64', 'latest,m
},
] + [
// publish for tag or master
docker('amd64', 'fluent-bit') {
clients_docker('amd64', 'fluent-bit') {
depends_on: ['image-tag'],
when: condition('include').tagMaster,
settings+: {
@ -102,7 +114,7 @@ local fluentbit() = pipeline('fluent-bit-amd64') + arch_image('amd64', 'latest,m
local fluentd() = pipeline('fluentd-amd64') + arch_image('amd64', 'latest,master') {
steps+: [
// dry run for everything that is not tag or master
docker('amd64', 'fluentd') {
clients_docker('amd64', 'fluentd') {
depends_on: ['image-tag'],
when: condition('exclude').tagMaster,
settings+: {
@ -112,7 +124,7 @@ local fluentd() = pipeline('fluentd-amd64') + arch_image('amd64', 'latest,master
},
] + [
// publish for tag or master
docker('amd64', 'fluentd') {
clients_docker('amd64', 'fluentd') {
depends_on: ['image-tag'],
when: condition('include').tagMaster,
settings+: {
@ -126,7 +138,7 @@ local fluentd() = pipeline('fluentd-amd64') + arch_image('amd64', 'latest,master
local logstash() = pipeline('logstash-amd64') + arch_image('amd64', 'latest,master') {
steps+: [
// dry run for everything that is not tag or master
docker('amd64', 'logstash') {
clients_docker('amd64', 'logstash') {
depends_on: ['image-tag'],
when: condition('exclude').tagMaster,
settings+: {
@ -136,7 +148,7 @@ local logstash() = pipeline('logstash-amd64') + arch_image('amd64', 'latest,mast
},
] + [
// publish for tag or master
docker('amd64', 'logstash') {
clients_docker('amd64', 'logstash') {
depends_on: ['image-tag'],
when: condition('include').tagMaster,
settings+: {
@ -147,6 +159,30 @@ local logstash() = pipeline('logstash-amd64') + arch_image('amd64', 'latest,mast
depends_on: ['check'],
};
local promtail(arch) = pipeline('promtail-' + arch) + arch_image(arch) {
steps+: [
// dry run for everything that is not tag or master
clients_docker(arch, 'promtail') {
depends_on: ['image-tag'],
when: condition('exclude').tagMaster,
settings+: {
dry_run: true,
build_args: ['TOUCH_PROTOS=1'],
},
}
] + [
// publish for tag or master
clients_docker(arch, 'promtail') {
depends_on: ['image-tag'],
when: condition('include').tagMaster,
settings+: {
build_args: ['TOUCH_PROTOS=1'],
},
}
],
depends_on: ['check'],
};
local multiarch_image(arch) = pipeline('docker-' + arch) + arch_image(arch) {
steps+: [
// dry run for everything that is not tag or master
@ -217,7 +253,10 @@ local manifest(apps) = pipeline('manifest') {
],
},
] + [
multiarch_image(arch) + (
multiarch_image(arch)
for arch in archs
] + [
promtail(arch) + (
// When we're building Promtail for ARM, we want to use Dockerfile.arm32 to fix
// a problem with the published Drone image. See Dockerfile.arm32 for more
// information.
@ -228,10 +267,10 @@ local manifest(apps) = pipeline('manifest') {
then {
steps: [
step + (
if std.objectHas(step, 'settings') && step.settings.dockerfile == 'cmd/promtail/Dockerfile'
if std.objectHas(step, 'settings') && step.settings.dockerfile == 'clients/cmd/promtail/Dockerfile'
then {
settings+: {
dockerfile: 'cmd/promtail/Dockerfile.arm32',
dockerfile: 'clients/cmd/promtail/Dockerfile.arm32',
},
}
else {}
@ -242,7 +281,7 @@ local manifest(apps) = pipeline('manifest') {
else {}
)
for arch in archs
] + [
] +[
fluentbit(),
fluentd(),
logstash(),

@ -99,27 +99,6 @@ steps:
depends_on:
- image-tag
- name: build-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/promtail/Dockerfile
dry_run: true
password:
from_secret: docker_password
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
exclude:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: build-logcli-image
image: plugins/docker
settings:
@ -179,25 +158,6 @@ steps:
depends_on:
- image-tag
- name: publish-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/promtail/Dockerfile
password:
from_secret: docker_password
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: publish-logcli-image
image: plugins/docker
settings:
@ -278,27 +238,6 @@ steps:
depends_on:
- image-tag
- name: build-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/promtail/Dockerfile
dry_run: true
password:
from_secret: docker_password
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
exclude:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: build-logcli-image
image: plugins/docker
settings:
@ -358,25 +297,6 @@ steps:
depends_on:
- image-tag
- name: publish-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/promtail/Dockerfile
password:
from_secret: docker_password
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: publish-logcli-image
image: plugins/docker
settings:
@ -457,16 +377,16 @@ steps:
depends_on:
- image-tag
- name: build-promtail-image
- name: build-logcli-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/promtail/Dockerfile.arm32
dockerfile: cmd/logcli/Dockerfile
dry_run: true
password:
from_secret: docker_password
repo: grafana/promtail
repo: grafana/logcli
username:
from_secret: docker_username
when:
@ -478,18 +398,94 @@ steps:
depends_on:
- image-tag
- name: build-logcli-image
- name: publish-loki-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/loki/Dockerfile
password:
from_secret: docker_password
repo: grafana/loki
username:
from_secret: docker_username
when:
ref:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: publish-loki-canary-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/loki-canary/Dockerfile
password:
from_secret: docker_password
repo: grafana/loki-canary
username:
from_secret: docker_username
when:
ref:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: publish-logcli-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/logcli/Dockerfile
dry_run: true
password:
from_secret: docker_password
repo: grafana/logcli
username:
from_secret: docker_username
when:
ref:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
depends_on:
- check
---
kind: pipeline
name: promtail-amd64
platform:
os: linux
arch: amd64
steps:
- name: image-tag
image: alpine
commands:
- apk add --no-cache bash git
- git fetch origin --tags
- echo $(./tools/image-tag)-amd64 > .tags
- name: build-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: clients/cmd/promtail/Dockerfile
dry_run: true
password:
from_secret: docker_password
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
exclude:
@ -499,15 +495,15 @@ steps:
depends_on:
- image-tag
- name: publish-loki-image
- name: publish-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/loki/Dockerfile
dockerfile: clients/cmd/promtail/Dockerfile
password:
from_secret: docker_password
repo: grafana/loki
repo: grafana/promtail
username:
from_secret: docker_username
when:
@ -518,22 +514,43 @@ steps:
depends_on:
- image-tag
- name: publish-loki-canary-image
depends_on:
- check
---
kind: pipeline
name: promtail-arm64
platform:
os: linux
arch: arm64
steps:
- name: image-tag
image: alpine
commands:
- apk add --no-cache bash git
- git fetch origin --tags
- echo $(./tools/image-tag)-arm64 > .tags
- name: build-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/loki-canary/Dockerfile
dockerfile: clients/cmd/promtail/Dockerfile
dry_run: true
password:
from_secret: docker_password
repo: grafana/loki-canary
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
exclude:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
@ -542,7 +559,7 @@ steps:
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/promtail/Dockerfile.arm32
dockerfile: clients/cmd/promtail/Dockerfile
password:
from_secret: docker_password
repo: grafana/promtail
@ -556,15 +573,55 @@ steps:
depends_on:
- image-tag
- name: publish-logcli-image
depends_on:
- check
---
kind: pipeline
name: promtail-arm
platform:
os: linux
arch: arm
steps:
- name: image-tag
image: alpine
commands:
- apk add --no-cache bash git
- git fetch origin --tags
- echo $(./tools/image-tag)-arm > .tags
- name: build-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: cmd/logcli/Dockerfile
dockerfile: clients/cmd/promtail/Dockerfile.arm32
dry_run: true
password:
from_secret: docker_password
repo: grafana/logcli
repo: grafana/promtail
username:
from_secret: docker_username
when:
ref:
exclude:
- refs/heads/master
- refs/heads/k??
- refs/tags/v*
depends_on:
- image-tag
- name: publish-promtail-image
image: plugins/docker
settings:
build_args:
- TOUCH_PROTOS=1
dockerfile: clients/cmd/promtail/Dockerfile.arm32
password:
from_secret: docker_password
repo: grafana/promtail
username:
from_secret: docker_username
when:
@ -598,7 +655,7 @@ steps:
- name: build-fluent-bit-image
image: plugins/docker
settings:
dockerfile: cmd/fluent-bit/Dockerfile
dockerfile: clients/cmd/fluent-bit/Dockerfile
dry_run: true
password:
from_secret: docker_password
@ -617,7 +674,7 @@ steps:
- name: publish-fluent-bit-image
image: plugins/docker
settings:
dockerfile: cmd/fluent-bit/Dockerfile
dockerfile: clients/cmd/fluent-bit/Dockerfile
password:
from_secret: docker_password
repo: grafana/fluent-bit-plugin-loki
@ -654,7 +711,7 @@ steps:
- name: build-fluentd-image
image: plugins/docker
settings:
dockerfile: cmd/fluentd/Dockerfile
dockerfile: clients/cmd/fluentd/Dockerfile
dry_run: true
password:
from_secret: docker_password
@ -673,7 +730,7 @@ steps:
- name: publish-fluentd-image
image: plugins/docker
settings:
dockerfile: cmd/fluentd/Dockerfile
dockerfile: clients/cmd/fluentd/Dockerfile
password:
from_secret: docker_password
repo: grafana/fluent-plugin-loki
@ -710,7 +767,7 @@ steps:
- name: build-logstash-image
image: plugins/docker
settings:
dockerfile: cmd/logstash/Dockerfile
dockerfile: clients/cmd/logstash/Dockerfile
dry_run: true
password:
from_secret: docker_password
@ -729,7 +786,7 @@ steps:
- name: publish-logstash-image
image: plugins/docker
settings:
dockerfile: cmd/logstash/Dockerfile
dockerfile: clients/cmd/logstash/Dockerfile
password:
from_secret: docker_password
repo: grafana/logstash-output-loki
@ -845,6 +902,6 @@ steps:
- name: test
image: golang:windowsservercore-1809
commands:
- go test .\pkg\promtail\targets\windows\... -v
- go test .\clients\pkg\promtail\targets\windows\... -v
...

10
.gitignore vendored

@ -10,13 +10,13 @@ requirements.lock
mixin/vendor/
cmd/loki/loki
cmd/logcli/logcli
cmd/promtail/promtail
clients/cmd/promtail/promtail
cmd/loki/loki-debug
cmd/promtail/promtail-debug
cmd/docker-driver/docker-driver
clients/cmd/promtail/promtail-debug
clients/cmd/docker-driver/docker-driver
cmd/loki-canary/loki-canary
cmd/fluent-bit/out_loki.so
cmd/fluent-bit/out_loki.h
clients/cmd/fluent-bit/out_grafana_loki.so
clients/cmd/fluent-bit/out_grafana_loki.h
cmd/migrate/migrate
/loki
/promtail

@ -89,8 +89,8 @@ YACC_DEFS := $(shell find . $(DONT_FIND) -type f -name *.y -print)
YACC_GOS := $(patsubst %.y,%.y.go,$(YACC_DEFS))
# Promtail UI files
PROMTAIL_GENERATED_FILE := pkg/promtail/server/ui/assets_vfsdata.go
PROMTAIL_UI_FILES := $(shell find ./pkg/promtail/server/ui -type f -name assets_vfsdata.go -prune -o -print)
PROMTAIL_GENERATED_FILE := clients/pkg/promtail/server/ui/assets_vfsdata.go
PROMTAIL_UI_FILES := $(shell find ./clients/pkg/promtail/server/ui -type f -name assets_vfsdata.go -prune -o -print)
##########
# Docker #
@ -127,7 +127,7 @@ binfmt:
all: promtail logcli loki loki-canary check-generated-files
# This is really a check for the CI to make sure generated files are built and checked in manually
check-generated-files: touch-protobuf-sources yacc protos pkg/promtail/server/ui/assets_vfsdata.go
check-generated-files: touch-protobuf-sources yacc protos clients/pkg/promtail/server/ui/assets_vfsdata.go
@if ! (git diff --exit-code $(YACC_GOS) $(PROTO_GOS) $(PROMTAIL_GENERATED_FILE)); then \
echo "\nChanges found in generated files"; \
echo "Run 'make check-generated-files' and commit the changes to fix this error."; \
@ -207,22 +207,22 @@ PROMTAIL_DEBUG_GO_FLAGS = $(DYN_DEBUG_GO_FLAGS)
endif
endif
promtail: yacc cmd/promtail/promtail
promtail-debug: yacc cmd/promtail/promtail-debug
promtail: yacc clients/cmd/promtail/promtail
promtail-debug: yacc clients/cmd/promtail/promtail-debug
promtail-clean-assets:
rm -rf pkg/promtail/server/ui/assets_vfsdata.go
rm -rf clients/pkg/promtail/server/ui/assets_vfsdata.go
# Rule to generate promtail static assets file
$(PROMTAIL_GENERATED_FILE): $(PROMTAIL_UI_FILES)
@echo ">> writing assets"
GOFLAGS="$(MOD_FLAG)" GOOS=$(shell go env GOHOSTOS) go generate -x -v ./pkg/promtail/server/ui
GOFLAGS="$(MOD_FLAG)" GOOS=$(shell go env GOHOSTOS) go generate -x -v ./clients/pkg/promtail/server/ui
cmd/promtail/promtail: $(APP_GO_FILES) $(PROMTAIL_GENERATED_FILE) cmd/promtail/main.go
clients/cmd/promtail/promtail: $(APP_GO_FILES) $(PROMTAIL_GENERATED_FILE) clients/cmd/promtail/main.go
CGO_ENABLED=$(PROMTAIL_CGO) go build $(PROMTAIL_GO_FLAGS) -o $@ ./$(@D)
$(NETGO_CHECK)
cmd/promtail/promtail-debug: $(APP_GO_FILES) pkg/promtail/server/ui/assets_vfsdata.go cmd/promtail/main.go
clients/cmd/promtail/promtail-debug: $(APP_GO_FILES) clients/pkg/promtail/server/ui/assets_vfsdata.go clients/cmd/promtail/main.go
CGO_ENABLED=$(PROMTAIL_CGO) go build $(PROMTAIL_DEBUG_GO_FLAGS) -o $@ ./$(@D)
$(NETGO_CHECK)
@ -246,8 +246,8 @@ dist: clean
CGO_ENABLED=0 $(GOX) -osarch="linux/amd64 linux/arm64 linux/arm darwin/amd64 windows/amd64 freebsd/amd64" ./cmd/loki
CGO_ENABLED=0 $(GOX) -osarch="linux/amd64 linux/arm64 linux/arm darwin/amd64 windows/amd64 freebsd/amd64" ./cmd/logcli
CGO_ENABLED=0 $(GOX) -osarch="linux/amd64 linux/arm64 linux/arm darwin/amd64 windows/amd64 freebsd/amd64" ./cmd/loki-canary
CGO_ENABLED=0 $(GOX) -osarch="linux/arm64 linux/arm darwin/amd64 windows/amd64 windows/386 freebsd/amd64" ./cmd/promtail
CGO_ENABLED=1 $(CGO_GOX) -osarch="linux/amd64" ./cmd/promtail
CGO_ENABLED=0 $(GOX) -osarch="linux/arm64 linux/arm darwin/amd64 windows/amd64 windows/386 freebsd/amd64" ./clients/cmd/promtail
CGO_ENABLED=1 $(CGO_GOX) -osarch="linux/amd64" ./clients/cmd/promtail
for i in dist/*; do zip -j -m $$i.zip $$i; done
pushd dist && sha256sum * > SHA256SUMS && popd
@ -274,16 +274,16 @@ test: all
#########
clean:
rm -rf cmd/promtail/promtail
rm -rf clients/cmd/promtail/promtail
rm -rf cmd/loki/loki
rm -rf cmd/logcli/logcli
rm -rf cmd/loki-canary/loki-canary
rm -rf cmd/querytee/querytee
rm -rf .cache
rm -rf cmd/docker-driver/rootfs
rm -rf clients/cmd/docker-driver/rootfs
rm -rf dist/
rm -rf cmd/fluent-bit/out_grafana_loki.h
rm -rf cmd/fluent-bit/out_grafana_loki.so
rm -rf clients/cmd/fluent-bit/out_grafana_loki.h
rm -rf clients/cmd/fluent-bit/out_grafana_loki.so
rm -rf cmd/migrate/migrate
go clean $(MOD_FLAG) ./...
@ -350,16 +350,16 @@ PLUGIN_TAG ?= $(IMAGE_TAG)
PLUGIN_ARCH ?=
docker-driver: docker-driver-clean
mkdir cmd/docker-driver/rootfs
docker build -t rootfsimage -f cmd/docker-driver/Dockerfile .
mkdir clients/cmd/docker-driver/rootfs
docker build -t rootfsimage -f clients/cmd/docker-driver/Dockerfile .
ID=$$(docker create rootfsimage true) && \
(docker export $$ID | tar -x -C cmd/docker-driver/rootfs) && \
(docker export $$ID | tar -x -C clients/cmd/docker-driver/rootfs) && \
docker rm -vf $$ID
docker rmi rootfsimage -f
docker plugin create $(LOKI_DOCKER_DRIVER):$(PLUGIN_TAG)$(PLUGIN_ARCH) cmd/docker-driver
docker plugin create $(LOKI_DOCKER_DRIVER):latest$(PLUGIN_ARCH) cmd/docker-driver
docker plugin create $(LOKI_DOCKER_DRIVER):$(PLUGIN_TAG)$(PLUGIN_ARCH) clients/cmd/docker-driver
docker plugin create $(LOKI_DOCKER_DRIVER):latest$(PLUGIN_ARCH) clients/cmd/docker-driver
cmd/docker-driver/docker-driver: $(APP_GO_FILES)
clients/cmd/docker-driver/docker-driver: $(APP_GO_FILES)
CGO_ENABLED=0 go build $(GO_FLAGS) -o $@ ./$(@D)
$(NETGO_CHECK)
@ -374,16 +374,16 @@ docker-driver-clean:
-docker plugin disable $(LOKI_DOCKER_DRIVER):$(PLUGIN_TAG)$(PLUGIN_ARCH)
-docker plugin rm $(LOKI_DOCKER_DRIVER):$(PLUGIN_TAG)$(PLUGIN_ARCH)
-docker plugin rm $(LOKI_DOCKER_DRIVER):latest$(PLUGIN_ARCH)
rm -rf cmd/docker-driver/rootfs
rm -rf clients/cmd/docker-driver/rootfs
#####################
# fluent-bit plugin #
#####################
fluent-bit-plugin:
go build $(DYN_GO_FLAGS) -buildmode=c-shared -o cmd/fluent-bit/out_grafana_loki.so ./cmd/fluent-bit/
go build $(DYN_GO_FLAGS) -buildmode=c-shared -o clients/cmd/fluent-bit/out_grafana_loki.so ./clients/cmd/fluent-bit/
fluent-bit-image:
$(SUDO) docker build -t $(IMAGE_PREFIX)/fluent-bit-plugin-loki:$(IMAGE_TAG) -f cmd/fluent-bit/Dockerfile .
$(SUDO) docker build -t $(IMAGE_PREFIX)/fluent-bit-plugin-loki:$(IMAGE_TAG) -f clients/cmd/fluent-bit/Dockerfile .
fluent-bit-push:
$(SUDO) $(PUSH_OCI) $(IMAGE_PREFIX)/fluent-bit-plugin-loki:$(IMAGE_TAG)
@ -400,28 +400,28 @@ fluent-bit-test:
fluentd-plugin:
gem install bundler --version 1.16.2
bundle config silence_root_warning true
bundle install --gemfile=cmd/fluentd/Gemfile --path=cmd/fluentd/vendor/bundle
bundle install --gemfile=clients/cmd/fluentd/Gemfile --path=clients/cmd/fluentd/vendor/bundle
fluentd-image:
$(SUDO) docker build -t $(IMAGE_PREFIX)/fluent-plugin-loki:$(IMAGE_TAG) -f cmd/fluentd/Dockerfile .
$(SUDO) docker build -t $(IMAGE_PREFIX)/fluent-plugin-loki:$(IMAGE_TAG) -f clients/cmd/fluentd/Dockerfile .
fluentd-push:
$(SUDO) $(PUSH_OCI) $(IMAGE_PREFIX)/fluent-plugin-loki:$(IMAGE_TAG)
fluentd-test: LOKI_URL ?= http://localhost:3100/loki/api/
fluentd-test:
LOKI_URL="$(LOKI_URL)" docker-compose -f cmd/fluentd/docker/docker-compose.yml up --build $(IMAGE_PREFIX)/fluent-plugin-loki:$(IMAGE_TAG)
LOKI_URL="$(LOKI_URL)" docker-compose -f clients/cmd/fluentd/docker/docker-compose.yml up --build $(IMAGE_PREFIX)/fluent-plugin-loki:$(IMAGE_TAG)
##################
# logstash plugin #
##################
logstash-image:
$(SUDO) docker build -t $(IMAGE_PREFIX)/logstash-output-loki:$(IMAGE_TAG) -f cmd/logstash/Dockerfile ./
$(SUDO) docker build -t $(IMAGE_PREFIX)/logstash-output-loki:$(IMAGE_TAG) -f clients/cmd/logstash/Dockerfile ./
# Send 10 lines to the local Loki instance.
logstash-push-test-logs: LOKI_URL ?= http://host.docker.internal:3100/loki/api/v1/push
logstash-push-test-logs:
$(SUDO) docker run -e LOKI_URL="$(LOKI_URL)" -v `pwd`/cmd/logstash/loki-test.conf:/home/logstash/loki.conf --rm \
$(SUDO) docker run -e LOKI_URL="$(LOKI_URL)" -v `pwd`/clients/cmd/logstash/loki-test.conf:/home/logstash/loki.conf --rm \
$(IMAGE_PREFIX)/logstash-output-loki:$(IMAGE_TAG) -f loki.conf
logstash-push:
@ -429,7 +429,7 @@ logstash-push:
# Enter an env already configure to build and test logstash output plugin.
logstash-env:
$(SUDO) docker run -v `pwd`/cmd/logstash:/home/logstash/ -it --rm --entrypoint /bin/sh $(IMAGE_PREFIX)/logstash-output-loki:$(IMAGE_TAG)
$(SUDO) docker run -v `pwd`/clients/cmd/logstash:/home/logstash/ -it --rm --entrypoint /bin/sh $(IMAGE_PREFIX)/logstash-output-loki:$(IMAGE_TAG)
########################
# Bigtable Backup Tool #
@ -474,13 +474,13 @@ endef
# promtail
promtail-image:
$(SUDO) docker build -t $(IMAGE_PREFIX)/promtail:$(IMAGE_TAG) -f cmd/promtail/Dockerfile .
$(SUDO) docker build -t $(IMAGE_PREFIX)/promtail:$(IMAGE_TAG) -f clients/cmd/promtail/Dockerfile .
promtail-image-cross:
$(SUDO) $(BUILD_OCI) -t $(IMAGE_PREFIX)/promtail:$(IMAGE_TAG) -f cmd/promtail/Dockerfile.cross .
$(SUDO) $(BUILD_OCI) -t $(IMAGE_PREFIX)/promtail:$(IMAGE_TAG) -f clients/cmd/promtail/Dockerfile.cross .
promtail-debug-image: OCI_PLATFORMS=
promtail-debug-image:
$(SUDO) $(BUILD_OCI) -t $(IMAGE_PREFIX)/promtail:$(IMAGE_TAG)-debug -f cmd/promtail/Dockerfile.debug .
$(SUDO) $(BUILD_OCI) -t $(IMAGE_PREFIX)/promtail:$(IMAGE_TAG)-debug -f clients/cmd/promtail/Dockerfile.debug .
promtail-push: promtail-image-cross
$(call push-image,promtail)

@ -7,10 +7,10 @@ ARG BUILD_IMAGE=grafana/loki-build-image:0.12.0
FROM $BUILD_IMAGE as build
COPY . /src/loki
WORKDIR /src/loki
RUN make clean && make BUILD_IN_CONTAINER=false cmd/docker-driver/docker-driver
RUN make clean && make BUILD_IN_CONTAINER=false clients/cmd/docker-driver/docker-driver
FROM alpine:3.13
RUN apk add --update --no-cache ca-certificates tzdata
COPY --from=build /src/loki/cmd/docker-driver/docker-driver /bin/docker-driver
COPY --from=build /src/loki/clients/cmd/docker-driver/docker-driver /bin/docker-driver
WORKDIR /bin/
ENTRYPOINT [ "/bin/docker-driver" ]

@ -3,6 +3,7 @@ package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/url"
"os"
"strconv"
@ -13,15 +14,16 @@ import (
"github.com/cortexproject/cortex/pkg/util/flagext"
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/daemon/logger/templates"
"github.com/pkg/errors"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/pkg/relabel"
yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
"github.com/grafana/loki/clients/pkg/logentry/stages"
"github.com/grafana/loki/clients/pkg/promtail/client"
"github.com/grafana/loki/clients/pkg/promtail/targets/file"
"github.com/grafana/loki/pkg/helpers"
"github.com/grafana/loki/pkg/logentry/stages"
"github.com/grafana/loki/pkg/promtail/client"
"github.com/grafana/loki/pkg/promtail/targets/file"
"github.com/grafana/loki/pkg/util"
)
@ -316,7 +318,7 @@ func parsePipeline(logCtx logger.Info) (PipelineConfig, error) {
return pipeline, fmt.Errorf("only one of %s or %s can be configured", cfgPipelineStagesFileKey, cfgPipelineStagesFileKey)
}
if okFile {
if err := helpers.LoadConfig(pipelineFile, &pipeline); err != nil {
if err := loadConfig(pipelineFile, &pipeline); err != nil {
return pipeline, fmt.Errorf("error loading config file %s: %s", pipelineFile, err)
}
}
@ -383,3 +385,13 @@ func parseBoolean(key string, logCtx logger.Info, defaultValue bool) (bool, erro
}
return b, nil
}
// loadConfig read YAML-formatted config from filename into cfg.
func loadConfig(filename string, cfg interface{}) error {
buf, err := ioutil.ReadFile(filename)
if err != nil {
return errors.Wrap(err, "Error reading config file")
}
return yaml.UnmarshalStrict(buf, cfg)
}

@ -13,7 +13,7 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/loki/pkg/logentry/stages"
"github.com/grafana/loki/clients/pkg/logentry/stages"
)
var jobRename = `

@ -9,10 +9,11 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"github.com/grafana/loki/pkg/logentry/stages"
"github.com/grafana/loki/clients/pkg/logentry/stages"
"github.com/grafana/loki/clients/pkg/promtail/api"
"github.com/grafana/loki/clients/pkg/promtail/client"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/promtail/api"
"github.com/grafana/loki/pkg/promtail/client"
)
var jobName = "docker"

@ -14,7 +14,7 @@ import (
"github.com/prometheus/common/version"
"github.com/weaveworks/common/logging"
_ "github.com/grafana/loki/pkg/build"
_ "github.com/grafana/loki/pkg/util/build"
)
const socketAddress = "/run/docker/plugins/loki.sock"

@ -4,7 +4,7 @@ WORKDIR /src/loki
RUN make clean && make BUILD_IN_CONTAINER=false fluent-bit-plugin
FROM fluent/fluent-bit:1.4
COPY --from=build /src/loki/cmd/fluent-bit/out_grafana_loki.so /fluent-bit/bin
COPY cmd/fluent-bit/fluent-bit.conf /fluent-bit/etc/fluent-bit.conf
COPY --from=build /src/loki/clients/cmd/fluent-bit/out_grafana_loki.so /fluent-bit/bin
COPY clients/cmd/fluent-bit/fluent-bit.conf /fluent-bit/etc/fluent-bit.conf
EXPOSE 2020
CMD ["/fluent-bit/bin/fluent-bit", "-e","/fluent-bit/bin/out_grafana_loki.so", "-c", "/fluent-bit/etc/fluent-bit.conf"]

@ -5,7 +5,7 @@ import (
"github.com/go-kit/kit/log"
"github.com/grafana/loki/pkg/promtail/client"
"github.com/grafana/loki/clients/pkg/promtail/client"
)
type bufferConfig struct {

@ -4,7 +4,7 @@ import (
"github.com/go-kit/kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/grafana/loki/pkg/promtail/client"
"github.com/grafana/loki/clients/pkg/promtail/client"
)
// NewClient creates a new client based on the fluentbit configuration.

@ -13,8 +13,9 @@ import (
"github.com/prometheus/common/model"
"github.com/weaveworks/common/logging"
"github.com/grafana/loki/pkg/logql"
"github.com/grafana/loki/pkg/promtail/client"
"github.com/grafana/loki/clients/pkg/logentry/logql"
"github.com/grafana/loki/clients/pkg/promtail/client"
lokiflag "github.com/grafana/loki/pkg/util/flagext"
)

@ -14,7 +14,8 @@ import (
"github.com/cortexproject/cortex/pkg/util/flagext"
"github.com/weaveworks/common/logging"
"github.com/grafana/loki/pkg/promtail/client"
"github.com/grafana/loki/clients/pkg/promtail/client"
lokiflag "github.com/grafana/loki/pkg/util/flagext"
)

@ -12,9 +12,10 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"github.com/grafana/loki/clients/pkg/promtail/api"
"github.com/grafana/loki/clients/pkg/promtail/client"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/promtail/api"
"github.com/grafana/loki/pkg/promtail/client"
)
type dqueConfig struct {

@ -16,9 +16,10 @@ import (
"github.com/prometheus/common/model"
"github.com/weaveworks/common/logging"
"github.com/grafana/loki/clients/pkg/promtail/api"
"github.com/grafana/loki/clients/pkg/promtail/client"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/promtail/api"
"github.com/grafana/loki/pkg/promtail/client"
)
var (

@ -9,9 +9,10 @@ import (
jsoniter "github.com/json-iterator/go"
"github.com/prometheus/common/model"
"github.com/grafana/loki/clients/pkg/promtail/api"
"github.com/grafana/loki/clients/pkg/promtail/client/fake"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/promtail/api"
"github.com/grafana/loki/pkg/promtail/client/fake"
)
var now = time.Now()

@ -1,18 +1,19 @@
package main
import (
"C"
"fmt"
"time"
"unsafe"
"C"
"github.com/fluent/fluent-bit-go/output"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/prometheus/common/version"
"github.com/weaveworks/common/logging"
_ "github.com/grafana/loki/pkg/build"
_ "github.com/grafana/loki/pkg/util/build"
)
var (

@ -12,10 +12,10 @@ RUN make BUILD_IN_CONTAINER=false fluentd-plugin
FROM fluent/fluentd:v1.9.2-debian-1.0
ENV LOKI_URL "https://logs-prod-us-central1.grafana.net"
COPY --from=build /src/loki/cmd/fluentd/lib/fluent/plugin/out_loki.rb /fluentd/plugins/out_loki.rb
COPY --from=build /src/loki/clients/cmd/fluentd/lib/fluent/plugin/out_loki.rb /fluentd/plugins/out_loki.rb
COPY cmd/fluentd/docker/Gemfile /fluentd/
COPY cmd/fluentd/docker/conf/loki.conf /fluentd/etc/loki.conf
COPY clients/cmd/fluentd/docker/Gemfile /fluentd/
COPY clients/cmd/fluentd/docker/conf/loki.conf /fluentd/etc/loki.conf
USER root
RUN sed -i '$i'' @include loki.conf' /fluentd/etc/fluent.conf

@ -3,8 +3,8 @@ services:
# Receive forwarded logs and send to /fluentd/logs/data.log and loki
fluentd:
build:
context: ../../..
dockerfile: cmd/fluentd/Dockerfile
context: ../../../..
dockerfile: ../Dockerfile
image: fluentd:loki
volumes:
- ./fluentd.conf:/fluentd/etc/fluent.conf

@ -8,7 +8,7 @@ ENV GEM_HOME /usr/share/logstash/vendor/bundle/jruby/2.5.0
RUN gem install bundler:2.1.4
COPY --chown=logstash:logstash ./cmd/logstash/ /home/logstash/
COPY --chown=logstash:logstash ./clients/cmd/logstash/ /home/logstash/
WORKDIR /home/logstash/

@ -19,7 +19,7 @@ RUN apt-get update && \
tzdata ca-certificates
RUN apt-get install -t buster-backports -qy libsystemd-dev && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=build /src/loki/cmd/promtail/promtail /usr/bin/promtail
COPY cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
COPY --from=build /src/loki/clients/cmd/promtail/promtail /usr/bin/promtail
COPY clients/cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
ENTRYPOINT ["/usr/bin/promtail"]
CMD ["-config.file=/etc/promtail/config.yml"]

@ -14,9 +14,9 @@ RUN apt-get update && \
apt-get install -qy \
tzdata ca-certificates libsystemd-dev && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=build /src/loki/cmd/promtail/promtail /usr/bin/promtail
COPY cmd/promtail/promtail-local-config.yaml /etc/promtail/local-config.yaml
COPY cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
COPY --from=build /src/loki/clients/cmd/promtail/promtail /usr/bin/promtail
COPY clients/cmd/promtail/promtail-local-config.yaml /etc/promtail/local-config.yaml
COPY clients/cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
# Drone CI builds arm32 images using armv8l rather than armv7l. Something in
# our build process above causes ldconfig to be rerun and removes the armhf

@ -1,7 +1,7 @@
ARG BUILD_IMAGE=grafana/loki-build-image:0.12.0
# Directories in this file are referenced from the root of the project not this folder
# This file is intended to be called from the root like so:
# docker build -t grafana/promtail -f cmd/promtail/Dockerfile .
# docker build -t grafana/promtail -f clients/cmd/promtail/Dockerfile .
FROM golang:1.16.2-alpine as goenv
RUN go env GOARCH > /goarch && \
go env GOARM > /goarm
@ -19,8 +19,8 @@ RUN apt-get update && \
apt-get install -qy \
tzdata ca-certificates libsystemd-dev && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=build /src/loki/cmd/promtail/promtail /usr/bin/promtail
COPY cmd/promtail/promtail-local-config.yaml /etc/promtail/local-config.yaml
COPY cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
COPY --from=build /src/loki/clients/cmd/promtail/promtail /usr/bin/promtail
COPY clients/cmd/promtail/promtail-local-config.yaml /etc/promtail/local-config.yaml
COPY clients/cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
ENTRYPOINT ["/usr/bin/promtail"]
CMD ["-config.file=/etc/promtail/config.yml"]

@ -1,6 +1,6 @@
# Directories in this file are referenced from the root of the project not this folder
# This file is intended to be called from the root like so:
# docker build -t grafana/promtail -f cmd/promtail/Dockerfile.debug .
# docker build -t grafana/promtail -f clients/cmd/promtail/Dockerfile.debug .
FROM grafana/loki-build-image as build
ARG GOARCH="amd64"
@ -11,10 +11,10 @@ RUN make clean && make BUILD_IN_CONTAINER=false promtail-debug
FROM alpine:3.13
RUN apk add --update --no-cache ca-certificates tzdata
COPY --from=build /src/loki/cmd/promtail/promtail-debug /usr/bin/promtail-debug
COPY --from=build /src/loki/clients/cmd/promtail/promtail-debug /usr/bin/promtail-debug
COPY --from=build /go/bin/dlv /usr/bin/dlv
COPY cmd/promtail/promtail-local-config.yaml /etc/promtail/local-config.yaml
COPY cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
COPY clients/cmd/promtail/promtail-local-config.yaml /etc/promtail/local-config.yaml
COPY clients/cmd/promtail/promtail-docker-config.yaml /etc/promtail/config.yml
# Expose 40000 for delve
EXPOSE 40000

@ -18,12 +18,13 @@ import (
// embed time zone data
_ "time/tzdata"
_ "github.com/grafana/loki/pkg/build"
"github.com/grafana/loki/pkg/cfg"
"github.com/grafana/loki/pkg/logentry/stages"
"github.com/grafana/loki/pkg/promtail"
"github.com/grafana/loki/pkg/promtail/config"
"github.com/grafana/loki/clients/pkg/logentry/stages"
"github.com/grafana/loki/clients/pkg/promtail"
"github.com/grafana/loki/clients/pkg/promtail/config"
logutil "github.com/grafana/loki/pkg/util"
_ "github.com/grafana/loki/pkg/util/build"
"github.com/grafana/loki/pkg/util/cfg"
)
func init() {

@ -0,0 +1,102 @@
package logql
import (
"bytes"
"fmt"
"regexp"
"github.com/prometheus/prometheus/pkg/labels"
)
// Filter is a line filter sent to a querier to filter out log line.
type Filter func([]byte) bool
// Expr is a LogQL expression.
type Expr interface {
Filter() (Filter, error)
Matchers() []*labels.Matcher
}
type matchersExpr struct {
matchers []*labels.Matcher
}
func (e *matchersExpr) Matchers() []*labels.Matcher {
return e.matchers
}
func (e *matchersExpr) Filter() (Filter, error) {
return nil, nil
}
type filterExpr struct {
left Expr
ty labels.MatchType
match string
}
func (e *filterExpr) Matchers() []*labels.Matcher {
return e.left.Matchers()
}
// NewFilterExpr wraps an existing Expr with a next filter expression.
func NewFilterExpr(left Expr, ty labels.MatchType, match string) Expr {
return &filterExpr{
left: left,
ty: ty,
match: match,
}
}
func (e *filterExpr) Filter() (Filter, error) {
var f func([]byte) bool
switch e.ty {
case labels.MatchRegexp:
re, err := regexp.Compile(e.match)
if err != nil {
return nil, err
}
f = re.Match
case labels.MatchNotRegexp:
re, err := regexp.Compile(e.match)
if err != nil {
return nil, err
}
f = func(line []byte) bool {
return !re.Match(line)
}
case labels.MatchEqual:
f = func(line []byte) bool {
return bytes.Contains(line, []byte(e.match))
}
case labels.MatchNotEqual:
f = func(line []byte) bool {
return !bytes.Contains(line, []byte(e.match))
}
default:
return nil, fmt.Errorf("unknow matcher: %v", e.match)
}
next, ok := e.left.(*filterExpr)
if ok {
nextFilter, err := next.Filter()
if err != nil {
return nil, err
}
return func(line []byte) bool {
return nextFilter(line) && f(line)
}, nil
}
return f, nil
}
func mustNewMatcher(t labels.MatchType, n, v string) *labels.Matcher {
m, err := labels.NewMatcher(t, n, v)
if err != nil {
panic(err)
}
return m
}

@ -0,0 +1,65 @@
%{
package logql
import (
"github.com/prometheus/prometheus/pkg/labels"
)
%}
%union{
Expr Expr
Filter labels.MatchType
Selector []*labels.Matcher
Matchers []*labels.Matcher
Matcher *labels.Matcher
str string
int int64
}
%start root
%type <Expr> expr
%type <Filter> filter
%type <Selector> selector
%type <Matchers> matchers
%type <Matcher> matcher
%token <str> IDENTIFIER STRING
%token <val> MATCHERS LABELS EQ NEQ RE NRE OPEN_BRACE CLOSE_BRACE COMMA DOT PIPE_MATCH PIPE_EXACT
%%
root: expr { exprlex.(*lexer).expr = $1 };
expr:
selector { $$ = &matchersExpr{ matchers: $1 } }
| expr filter STRING { $$ = NewFilterExpr( $1, $2, $3 ) }
| expr filter error
| expr error
;
filter:
PIPE_MATCH { $$ = labels.MatchRegexp }
| PIPE_EXACT { $$ = labels.MatchEqual }
| NRE { $$ = labels.MatchNotRegexp }
| NEQ { $$ = labels.MatchNotEqual }
;
selector:
OPEN_BRACE matchers CLOSE_BRACE { $$ = $2 }
| OPEN_BRACE matchers error { $$ = $2 }
| OPEN_BRACE error CLOSE_BRACE { }
;
matchers:
matcher { $$ = []*labels.Matcher{ $1 } }
| matchers COMMA matcher { $$ = append($1, $3) }
;
matcher:
IDENTIFIER EQ STRING { $$ = mustNewMatcher(labels.MatchEqual, $1, $3) }
| IDENTIFIER NEQ STRING { $$ = mustNewMatcher(labels.MatchNotEqual, $1, $3) }
| IDENTIFIER RE STRING { $$ = mustNewMatcher(labels.MatchRegexp, $1, $3) }
| IDENTIFIER NRE STRING { $$ = mustNewMatcher(labels.MatchNotRegexp, $1, $3) }
;
%%

@ -0,0 +1,542 @@
// Code generated by goyacc -p expr -o clients/pkg/logentry/logql/expr.y.go clients/pkg/logentry/logql/expr.y. DO NOT EDIT.
package logql
import __yyfmt__ "fmt"
import (
"github.com/prometheus/prometheus/pkg/labels"
)
type exprSymType struct {
yys int
Expr Expr
Filter labels.MatchType
Selector []*labels.Matcher
Matchers []*labels.Matcher
Matcher *labels.Matcher
str string
int int64
}
const IDENTIFIER = 57346
const STRING = 57347
const MATCHERS = 57348
const LABELS = 57349
const EQ = 57350
const NEQ = 57351
const RE = 57352
const NRE = 57353
const OPEN_BRACE = 57354
const CLOSE_BRACE = 57355
const COMMA = 57356
const DOT = 57357
const PIPE_MATCH = 57358
const PIPE_EXACT = 57359
var exprToknames = [...]string{
"$end",
"error",
"$unk",
"IDENTIFIER",
"STRING",
"MATCHERS",
"LABELS",
"EQ",
"NEQ",
"RE",
"NRE",
"OPEN_BRACE",
"CLOSE_BRACE",
"COMMA",
"DOT",
"PIPE_MATCH",
"PIPE_EXACT",
}
var exprStatenames = [...]string{}
const exprEofCode = 1
const exprErrCode = 2
const exprInitialStackSize = 16
var exprExca = [...]int{
-1, 1,
1, -1,
-2, 0,
-1, 2,
1, 1,
-2, 0,
}
const exprPrivate = 57344
const exprLast = 30
var exprAct = [...]int{
6, 13, 20, 4, 29, 18, 28, 10, 14, 9,
21, 22, 23, 24, 7, 8, 17, 19, 27, 16,
26, 25, 15, 12, 11, 14, 3, 5, 2, 1,
}
var exprPact = [...]int{
-9, -1000, -2, -1000, 21, 17, -1000, -1000, -1000, -1000,
-1000, 3, -11, -1000, 2, -1000, -1000, -1000, -1000, 4,
-1000, 15, 13, 1, -1, -1000, -1000, -1000, -1000, -1000,
}
var exprPgo = [...]int{
0, 29, 28, 27, 26, 24, 1,
}
var exprR1 = [...]int{
0, 1, 2, 2, 2, 2, 3, 3, 3, 3,
4, 4, 4, 5, 5, 6, 6, 6, 6,
}
var exprR2 = [...]int{
0, 1, 1, 3, 3, 2, 1, 1, 1, 1,
3, 3, 3, 1, 3, 3, 3, 3, 3,
}
var exprChk = [...]int{
-1000, -1, -2, -4, 12, -3, 2, 16, 17, 11,
9, -5, 2, -6, 4, 5, 2, 13, 2, 14,
13, 8, 9, 10, 11, -6, 5, 5, 5, 5,
}
var exprDef = [...]int{
0, -2, -2, 2, 0, 0, 5, 6, 7, 8,
9, 0, 0, 13, 0, 3, 4, 10, 11, 0,
12, 0, 0, 0, 0, 14, 15, 16, 17, 18,
}
var exprTok1 = [...]int{
1,
}
var exprTok2 = [...]int{
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17,
}
var exprTok3 = [...]int{
0,
}
var exprErrorMessages = [...]struct {
state int
token int
msg string
}{}
/* parser for yacc output */
var (
exprDebug = 0
exprErrorVerbose = false
)
type exprLexer interface {
Lex(lval *exprSymType) int
Error(s string)
}
type exprParser interface {
Parse(exprLexer) int
Lookahead() int
}
type exprParserImpl struct {
lval exprSymType
stack [exprInitialStackSize]exprSymType
char int
}
func (p *exprParserImpl) Lookahead() int {
return p.char
}
func exprNewParser() exprParser {
return &exprParserImpl{}
}
const exprFlag = -1000
func exprTokname(c int) string {
if c >= 1 && c-1 < len(exprToknames) {
if exprToknames[c-1] != "" {
return exprToknames[c-1]
}
}
return __yyfmt__.Sprintf("tok-%v", c)
}
func exprStatname(s int) string {
if s >= 0 && s < len(exprStatenames) {
if exprStatenames[s] != "" {
return exprStatenames[s]
}
}
return __yyfmt__.Sprintf("state-%v", s)
}
func exprErrorMessage(state, lookAhead int) string {
const TOKSTART = 4
if !exprErrorVerbose {
return "syntax error"
}
for _, e := range exprErrorMessages {
if e.state == state && e.token == lookAhead {
return "syntax error: " + e.msg
}
}
res := "syntax error: unexpected " + exprTokname(lookAhead)
// To match Bison, suggest at most four expected tokens.
expected := make([]int, 0, 4)
// Look for shiftable tokens.
base := exprPact[state]
for tok := TOKSTART; tok-1 < len(exprToknames); tok++ {
if n := base + tok; n >= 0 && n < exprLast && exprChk[exprAct[n]] == tok {
if len(expected) == cap(expected) {
return res
}
expected = append(expected, tok)
}
}
if exprDef[state] == -2 {
i := 0
for exprExca[i] != -1 || exprExca[i+1] != state {
i += 2
}
// Look for tokens that we accept or reduce.
for i += 2; exprExca[i] >= 0; i += 2 {
tok := exprExca[i]
if tok < TOKSTART || exprExca[i+1] == 0 {
continue
}
if len(expected) == cap(expected) {
return res
}
expected = append(expected, tok)
}
// If the default action is to accept or reduce, give up.
if exprExca[i+1] != 0 {
return res
}
}
for i, tok := range expected {
if i == 0 {
res += ", expecting "
} else {
res += " or "
}
res += exprTokname(tok)
}
return res
}
func exprlex1(lex exprLexer, lval *exprSymType) (char, token int) {
token = 0
char = lex.Lex(lval)
if char <= 0 {
token = exprTok1[0]
goto out
}
if char < len(exprTok1) {
token = exprTok1[char]
goto out
}
if char >= exprPrivate {
if char < exprPrivate+len(exprTok2) {
token = exprTok2[char-exprPrivate]
goto out
}
}
for i := 0; i < len(exprTok3); i += 2 {
token = exprTok3[i+0]
if token == char {
token = exprTok3[i+1]
goto out
}
}
out:
if token == 0 {
token = exprTok2[1] /* unknown char */
}
if exprDebug >= 3 {
__yyfmt__.Printf("lex %s(%d)\n", exprTokname(token), uint(char))
}
return char, token
}
func exprParse(exprlex exprLexer) int {
return exprNewParser().Parse(exprlex)
}
func (exprrcvr *exprParserImpl) Parse(exprlex exprLexer) int {
var exprn int
var exprVAL exprSymType
var exprDollar []exprSymType
_ = exprDollar // silence set and not used
exprS := exprrcvr.stack[:]
Nerrs := 0 /* number of errors */
Errflag := 0 /* error recovery flag */
exprstate := 0
exprrcvr.char = -1
exprtoken := -1 // exprrcvr.char translated into internal numbering
defer func() {
// Make sure we report no lookahead when not parsing.
exprstate = -1
exprrcvr.char = -1
exprtoken = -1
}()
exprp := -1
goto exprstack
ret0:
return 0
ret1:
return 1
exprstack:
/* put a state and value onto the stack */
if exprDebug >= 4 {
__yyfmt__.Printf("char %v in %v\n", exprTokname(exprtoken), exprStatname(exprstate))
}
exprp++
if exprp >= len(exprS) {
nyys := make([]exprSymType, len(exprS)*2)
copy(nyys, exprS)
exprS = nyys
}
exprS[exprp] = exprVAL
exprS[exprp].yys = exprstate
exprnewstate:
exprn = exprPact[exprstate]
if exprn <= exprFlag {
goto exprdefault /* simple state */
}
if exprrcvr.char < 0 {
exprrcvr.char, exprtoken = exprlex1(exprlex, &exprrcvr.lval)
}
exprn += exprtoken
if exprn < 0 || exprn >= exprLast {
goto exprdefault
}
exprn = exprAct[exprn]
if exprChk[exprn] == exprtoken { /* valid shift */
exprrcvr.char = -1
exprtoken = -1
exprVAL = exprrcvr.lval
exprstate = exprn
if Errflag > 0 {
Errflag--
}
goto exprstack
}
exprdefault:
/* default state action */
exprn = exprDef[exprstate]
if exprn == -2 {
if exprrcvr.char < 0 {
exprrcvr.char, exprtoken = exprlex1(exprlex, &exprrcvr.lval)
}
/* look through exception table */
xi := 0
for {
if exprExca[xi+0] == -1 && exprExca[xi+1] == exprstate {
break
}
xi += 2
}
for xi += 2; ; xi += 2 {
exprn = exprExca[xi+0]
if exprn < 0 || exprn == exprtoken {
break
}
}
exprn = exprExca[xi+1]
if exprn < 0 {
goto ret0
}
}
if exprn == 0 {
/* error ... attempt to resume parsing */
switch Errflag {
case 0: /* brand new error */
exprlex.Error(exprErrorMessage(exprstate, exprtoken))
Nerrs++
if exprDebug >= 1 {
__yyfmt__.Printf("%s", exprStatname(exprstate))
__yyfmt__.Printf(" saw %s\n", exprTokname(exprtoken))
}
fallthrough
case 1, 2: /* incompletely recovered error ... try again */
Errflag = 3
/* find a state where "error" is a legal shift action */
for exprp >= 0 {
exprn = exprPact[exprS[exprp].yys] + exprErrCode
if exprn >= 0 && exprn < exprLast {
exprstate = exprAct[exprn] /* simulate a shift of "error" */
if exprChk[exprstate] == exprErrCode {
goto exprstack
}
}
/* the current p has no shift on "error", pop stack */
if exprDebug >= 2 {
__yyfmt__.Printf("error recovery pops state %d\n", exprS[exprp].yys)
}
exprp--
}
/* there is no state on the stack with an error shift ... abort */
goto ret1
case 3: /* no shift yet; clobber input char */
if exprDebug >= 2 {
__yyfmt__.Printf("error recovery discards %s\n", exprTokname(exprtoken))
}
if exprtoken == exprEofCode {
goto ret1
}
exprrcvr.char = -1
exprtoken = -1
goto exprnewstate /* try again in the same state */
}
}
/* reduction by production exprn */
if exprDebug >= 2 {
__yyfmt__.Printf("reduce %v in:\n\t%v\n", exprn, exprStatname(exprstate))
}
exprnt := exprn
exprpt := exprp
_ = exprpt // guard against "declared and not used"
exprp -= exprR2[exprn]
// exprp is now the index of $0. Perform the default action. Iff the
// reduced production is ε, $1 is possibly out of range.
if exprp+1 >= len(exprS) {
nyys := make([]exprSymType, len(exprS)*2)
copy(nyys, exprS)
exprS = nyys
}
exprVAL = exprS[exprp+1]
/* consult goto table to find next state */
exprn = exprR1[exprn]
exprg := exprPgo[exprn]
exprj := exprg + exprS[exprp].yys + 1
if exprj >= exprLast {
exprstate = exprAct[exprg]
} else {
exprstate = exprAct[exprj]
if exprChk[exprstate] != -exprn {
exprstate = exprAct[exprg]
}
}
// dummy call; replaced with literal code
switch exprnt {
case 1:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprlex.(*lexer).expr = exprDollar[1].Expr
}
case 2:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Expr = &matchersExpr{matchers: exprDollar[1].Selector}
}
case 3:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Expr = NewFilterExpr(exprDollar[1].Expr, exprDollar[2].Filter, exprDollar[3].str)
}
case 6:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Filter = labels.MatchRegexp
}
case 7:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Filter = labels.MatchEqual
}
case 8:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Filter = labels.MatchNotRegexp
}
case 9:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Filter = labels.MatchNotEqual
}
case 10:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Selector = exprDollar[2].Matchers
}
case 11:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Selector = exprDollar[2].Matchers
}
case 12:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
}
case 13:
exprDollar = exprS[exprpt-1 : exprpt+1]
{
exprVAL.Matchers = []*labels.Matcher{exprDollar[1].Matcher}
}
case 14:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Matchers = append(exprDollar[1].Matchers, exprDollar[3].Matcher)
}
case 15:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Matcher = mustNewMatcher(labels.MatchEqual, exprDollar[1].str, exprDollar[3].str)
}
case 16:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Matcher = mustNewMatcher(labels.MatchNotEqual, exprDollar[1].str, exprDollar[3].str)
}
case 17:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Matcher = mustNewMatcher(labels.MatchRegexp, exprDollar[1].str, exprDollar[3].str)
}
case 18:
exprDollar = exprS[exprpt-3 : exprpt+1]
{
exprVAL.Matcher = mustNewMatcher(labels.MatchNotRegexp, exprDollar[1].str, exprDollar[3].str)
}
}
goto exprstack /* stack new state and value */
}

@ -0,0 +1,118 @@
package logql
import (
"errors"
"fmt"
"strconv"
"strings"
"text/scanner"
"github.com/prometheus/prometheus/pkg/labels"
)
func init() {
// Improve the error messages coming out of yacc.
exprErrorVerbose = true
for str, tok := range tokens {
exprToknames[tok-exprPrivate+1] = str
}
}
// ParseExpr parses a string and returns an Expr.
func ParseExpr(input string) (Expr, error) {
l := lexer{
parser: exprNewParser().(*exprParserImpl),
}
l.Init(strings.NewReader(input))
l.Scanner.Error = func(_ *scanner.Scanner, msg string) {
l.Error(msg)
}
e := l.parser.Parse(&l)
if e != 0 || len(l.errs) > 0 {
return nil, l.errs[0]
}
return l.expr, nil
}
// ParseMatchers parses a string and returns labels matchers, if the expression contains
// anything else it will return an error.
func ParseMatchers(input string) ([]*labels.Matcher, error) {
expr, err := ParseExpr(input)
if err != nil {
return nil, err
}
matcherExpr, ok := expr.(*matchersExpr)
if !ok {
return nil, errors.New("only label matchers is supported")
}
return matcherExpr.matchers, nil
}
var tokens = map[string]int{
",": COMMA,
".": DOT,
"{": OPEN_BRACE,
"}": CLOSE_BRACE,
"=": EQ,
"!=": NEQ,
"=~": RE,
"!~": NRE,
"|=": PIPE_EXACT,
"|~": PIPE_MATCH,
}
type lexer struct {
scanner.Scanner
errs []ParseError
expr Expr
parser *exprParserImpl
}
func (l *lexer) Lex(lval *exprSymType) int {
r := l.Scan()
switch r {
case scanner.EOF:
return 0
case scanner.String:
var err error
lval.str, err = strconv.Unquote(l.TokenText())
if err != nil {
l.Error(err.Error())
return 0
}
return STRING
}
if tok, ok := tokens[l.TokenText()+string(l.Peek())]; ok {
l.Next()
return tok
}
if tok, ok := tokens[l.TokenText()]; ok {
return tok
}
lval.str = l.TokenText()
return IDENTIFIER
}
func (l *lexer) Error(msg string) {
l.errs = append(l.errs, ParseError{
msg: msg,
line: l.Line,
col: l.Column,
})
}
// ParseError is what is returned when we failed to parse.
type ParseError struct {
msg string
line, col int
}
func (p ParseError) Error() string {
return fmt.Sprintf("parse error at line %d, col %d: %s", p.line, p.col, p.msg)
}

@ -0,0 +1,157 @@
package logql
import (
"strings"
"testing"
"text/scanner"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/stretchr/testify/require"
)
func TestLex(t *testing.T) {
for _, tc := range []struct {
input string
expected []int
}{
{`{foo="bar"}`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE}},
{`{ foo = "bar" }`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE}},
{`{ foo != "bar" }`, []int{OPEN_BRACE, IDENTIFIER, NEQ, STRING, CLOSE_BRACE}},
{`{ foo =~ "bar" }`, []int{OPEN_BRACE, IDENTIFIER, RE, STRING, CLOSE_BRACE}},
{`{ foo !~ "bar" }`, []int{OPEN_BRACE, IDENTIFIER, NRE, STRING, CLOSE_BRACE}},
{`{ foo = "bar", bar != "baz" }`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING,
COMMA, IDENTIFIER, NEQ, STRING, CLOSE_BRACE}},
{`{ foo = "ba\"r" }`, []int{OPEN_BRACE, IDENTIFIER, EQ, STRING, CLOSE_BRACE}},
} {
t.Run(tc.input, func(t *testing.T) {
actual := []int{}
l := lexer{
Scanner: scanner.Scanner{
Mode: scanner.SkipComments | scanner.ScanStrings,
},
}
l.Init(strings.NewReader(tc.input))
var lval exprSymType
for {
tok := l.Lex(&lval)
if tok == 0 {
break
}
actual = append(actual, tok)
}
require.Equal(t, tc.expected, actual)
})
}
}
func TestParse(t *testing.T) {
for _, tc := range []struct {
in string
exp Expr
err error
}{
{
in: `{foo="bar"}`,
exp: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
},
{
in: `{ foo = "bar" }`,
exp: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
},
{
in: `{ foo != "bar" }`,
exp: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchNotEqual, "foo", "bar")}},
},
{
in: `{ foo =~ "bar" }`,
exp: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchRegexp, "foo", "bar")}},
},
{
in: `{ foo !~ "bar" }`,
exp: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchNotRegexp, "foo", "bar")}},
},
{
in: `{ foo = "bar", bar != "baz" }`,
exp: &matchersExpr{matchers: []*labels.Matcher{
mustNewMatcher(labels.MatchEqual, "foo", "bar"),
mustNewMatcher(labels.MatchNotEqual, "bar", "baz"),
}},
},
{
in: `{foo="bar"} |= "baz"`,
exp: &filterExpr{
left: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
ty: labels.MatchEqual,
match: "baz",
},
},
{
in: `{foo="bar"} |= "baz" |~ "blip" != "flip" !~ "flap"`,
exp: &filterExpr{
left: &filterExpr{
left: &filterExpr{
left: &filterExpr{
left: &matchersExpr{matchers: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "foo", "bar")}},
ty: labels.MatchEqual,
match: "baz",
},
ty: labels.MatchRegexp,
match: "blip",
},
ty: labels.MatchNotEqual,
match: "flip",
},
ty: labels.MatchNotRegexp,
match: "flap",
},
},
{
in: `{foo="bar}`,
err: ParseError{
msg: "literal not terminated",
line: 1,
col: 6,
},
},
{
in: `{foo="bar"`,
err: ParseError{
msg: "syntax error: unexpected $end, expecting } or ,",
line: 1,
col: 11,
},
},
{
in: `{foo="bar"} |~`,
err: ParseError{
msg: "syntax error: unexpected $end, expecting STRING",
line: 1,
col: 15,
},
},
{
in: `{foo="bar"} "foo"`,
err: ParseError{
msg: "syntax error: unexpected STRING, expecting != or !~ or |~ or |=",
line: 1,
col: 13,
},
},
{
in: `{foo="bar"} foo`,
err: ParseError{
msg: "syntax error: unexpected IDENTIFIER, expecting != or !~ or |~ or |=",
line: 1,
col: 13,
},
},
} {
t.Run(tc.in, func(t *testing.T) {
ast, err := ParseExpr(tc.in)
require.Equal(t, tc.err, err)
require.Equal(t, tc.exp, ast)
})
}
}

@ -9,10 +9,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/logql"
"github.com/grafana/loki/pkg/promtail/api"
"github.com/grafana/loki/pkg/util"
"github.com/grafana/loki/clients/pkg/logentry/logql"
)
const (
@ -37,7 +34,7 @@ type MatcherConfig struct {
}
// validateMatcherConfig validates the MatcherConfig for the matcherStage
func validateMatcherConfig(cfg *MatcherConfig) (logql.LogSelectorExpr, error) {
func validateMatcherConfig(cfg *MatcherConfig) (logql.Expr, error) {
if cfg == nil {
return nil, errors.New(ErrEmptyMatchStageConfig)
}
@ -62,7 +59,7 @@ func validateMatcherConfig(cfg *MatcherConfig) (logql.LogSelectorExpr, error) {
return nil, errors.New(ErrStagesWithDropLine)
}
selector, err := logql.ParseLogSelector(cfg.Selector, false)
selector, err := logql.ParseExpr(cfg.Selector)
if err != nil {
return nil, errors.Wrap(err, ErrSelectorSyntax)
}
@ -96,7 +93,7 @@ func newMatcherStage(logger log.Logger, jobName *string, config interface{}, reg
}
}
pipeline, err := selector.Pipeline()
filter, err := selector.Filter()
if err != nil {
return nil, errors.Wrap(err, "error parsing pipeline")
}
@ -112,7 +109,7 @@ func newMatcherStage(logger log.Logger, jobName *string, config interface{}, reg
matchers: selector.Matchers(),
stage: pl,
action: cfg.Action,
pipeline: pipeline,
filter: filter,
}, nil
}
@ -139,7 +136,7 @@ type matcherStage struct {
dropReason string
dropCount *prometheus.CounterVec
matchers []*labels.Matcher
pipeline logql.Pipeline
filter logql.Filter
stage Stage
action string
}
@ -199,27 +196,11 @@ func (m *matcherStage) processLogQL(e Entry) (Entry, bool) {
return e, false
}
}
sp := m.pipeline.ForStream(labels.FromMap(util.ModelLabelSetToMap(e.Labels)))
newLine, newLabels, ok := sp.ProcessString(e.Line)
if !ok {
return e, false
}
for k := range e.Labels {
delete(e.Labels, k)
}
for _, l := range newLabels.Labels() {
e.Labels[model.LabelName(l.Name)] = model.LabelValue(l.Value)
}
return Entry{
Extracted: e.Extracted,
Entry: api.Entry{
Labels: e.Labels,
Entry: logproto.Entry{
Line: newLine,
Timestamp: e.Timestamp,
},
},
}, true
if m.filter == nil || m.filter([]byte(e.Line)) {
return e, true
}
return e, false
}
// Name implements Stage

@ -15,7 +15,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"github.com/grafana/loki/pkg/logentry/metric"
"github.com/grafana/loki/clients/pkg/logentry/metric"
)
const (

@ -14,7 +14,7 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/grafana/loki/pkg/logentry/metric"
"github.com/grafana/loki/clients/pkg/logentry/metric"
)
var testMetricYaml = `

@ -13,8 +13,9 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/common/model"
"github.com/grafana/loki/clients/pkg/promtail/api"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/promtail/api"
)
const (

@ -11,8 +11,9 @@ import (
"github.com/stretchr/testify/require"
ww "github.com/weaveworks/common/server"
"github.com/grafana/loki/clients/pkg/promtail/api"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/promtail/api"
)
func Test_multilineStage_Process(t *testing.T) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save