Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to use existing processors from script processor #11260

Merged
merged 11 commits into from
Mar 21, 2019

Conversation

andrewkroh
Copy link
Member

@andrewkroh andrewkroh commented Mar 15, 2019

This adds a require function to the JS runtime that scripts can call to import
"modules". The modules that are added in this PR are

  • processor - You can construct beat processors in JS (e.g. new processor.Dissect({...})).
  • console - You can write to beat's logger.
  • path - You can parse win32 and posix paths.

The processor module supports constructing:

  • AddCloudMetadata
  • AddDockerMetadata
  • AddHostMetadata
  • AddKubernetesMetadata
  • AddLocale
  • AddProcessMetadata
  • CommunityID
  • DecodeJSONFields
  • Dissect
  • DNS

Basic Example

This is a basic example. It's nothing you couldn't do already with the YAML format, but imagine you need to start adding in some more complex conditions and following some conditional branches.

var console = require('console');
var processor = require('processor');

var dissect = new processor.Dissect({
    tokenizer: "pid=%{process.pid}|ppid=%{process.ppid}|",
});
var processMetadata = new processor.AddProcessMetadata({
    match_pids: ["dissect.process.pid"],
});
var parentMetadata = new processor.AddProcessMetadata({
    match_pids: ["dissect.process.ppid"],
    target: "process.parent",
});

function process(event) {
    console.log("fields: %j", event.fields);
    dissect.Run(event);
    processMetadata.Run(event);
    parentMetadata.Run(event);
    event.Delete("dissect");
    event.Rename("message", "log.original");
}

Copy link
Contributor

@ph ph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really minor changes, I've inspect the added goja code too.

}

func newAddLocale(c *common.Config) (processors.Processor, error) {
// New constructs a new add_locale processor.
func New(c *common.Config) (processors.Processor, error) {
config := struct {
Format string `config:"format"`
}{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice little refactoring.


import (
"github.com/dop251/goja"
"github.com/dop251/goja_nodejs/require"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've inspected the package from goja everything is clean 👍


log := logp.L().Named("processor.javascript")
switch level {
case logp.DebugLevel:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we missing Info?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad you brought this up. For some reason I had it in my head that the typical console API in the browser didn't have an info. But I was wrong. https://developer.mozilla.org/en-US/docs/Web/API/Console/info

I'll add this.

o.Set("log", c.makeLogFunc(logp.DebugLevel))
o.Set("warn", c.makeLogFunc(logp.WarnLevel))
o.Set("error", c.makeLogFunc(logp.ErrorLevel))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we are trying to add a convenience debug method of console, It's bad that console doesn't completely map to the our Error Level, we might want to consider to alias info(), debug() to log().

Or by looking at the code we don't allow a user to use the info level, I am wondering if we should permit that by either allow info() to log to the info level. official doc

Another way would be to expose logp as new module with the method mapped to the right level.

}
`

logp.TestingSetup(logp.ToObserverOutput())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL

return b.volAndPath[:b.volLen+b.w]
}
return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to add unit test for the windows path handling.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some tests in path_test.go for Windows.


func (bp *beatProcessor) Run(call goja.FunctionCall) goja.Value {
if len(call.Arguments) != 1 {
panic(bp.runtime.NewGoError(errors.Errorf("Run requires one argument")))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run -> run?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run is the name of the function that's exposed in the JS. That's why it's capitalized.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should have been more precise I was talking about the string user in Errorf

errors.Errorf("Run requires one argument")

//
// // javascript
// var processor = require('processor');
// var chopLog = new processor.Dissect({tokenizer: "%{key}: %{value}"});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ph
Copy link
Contributor

ph commented Mar 20, 2019

@andrewkroh you will need to run make fmt to fix the CI.

This adds a `require` function to the JS runtime that scripts can call to import
"modules". Some standard modules that are added in this PR are

- `processor` - You can construct beat processors in JS (e.g. `new processor.Dissect({...})`).
- `console` - You can write to beat's logger.
- `path` - You can parse win32 and posix paths.

The `processor` module supports constructing:

- `AddCloudMetadata`
- `AddDockerMetadata`
- `AddHostMetadata`
- `AddKubernetesMetadata`
- `AddLocale`
- `AddProcessMetadata`
- `CommunityID`
- `DecodeJSONFields`
- `Dissect`
- `DNS`
The module registry is a global so 'console' is only initialized once. But if logp is reinitialized the stored logger would have the old settings. So don't use a global logger.
@andrewkroh
Copy link
Member Author

@ph So I added console.debug() and console.info. Then I make console.log be effectively an alias to console.info(). Plus I ran make fmt.

@ph
Copy link
Contributor

ph commented Mar 21, 2019

@andrewkroh changes look good, only the Errorf message and there is still a test failling on travis.

command [go test -cover -coverprofile /tmp/gotestcover-280386040 github.com/elastic/beats/libbeat/processors/script/javascript/module/console]: exit status 1
--- FAIL: TestConsole (0.00s)
    console_test.go:60: 
        	Error Trace:	console_test.go:60
        	Error:      	Expected value not to be nil.
        	Test:       	TestConsole
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xa6e066]
goroutine 20 [running]:
testing.tRunner.func1(0xc00013a200)
	/home/travis/.gimme/versions/go1.11.5.linux.amd64/

Use logp.DevelopmentSetup and not TestingSetup.
@andrewkroh
Copy link
Member Author

I'm pretty sure I figured out the problem with the test now. I should really read the godocs that I wrote next time. 🤦‍♂️ logp.TestingSetup only initializes the logger when -v is used, but this test always needs it setup so I needed to use logp.DevelopmentSetup.

@andrewkroh andrewkroh merged commit d36eb5a into elastic:master Mar 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants