fluent-bit lua parse by namespace - fluent-bit

I have multiple namespaces and I want the data from each namespace to be sent to a different topic
Example namespaces:
011231564
012387455
...
I have code in lua
if the namespace starts with "00"
function namespace(tag, timestamp, record)
if string.sub(record["kubernetes"]["namespace"], 1, 10) == "0" then
record["topic"] = "cluster-0" .. string.sub(record["kubernetes"]["namespace"], 4)
return 1, timestamp, record
end
return 0, 0, 0
end
But the above code ends with a substring error

Related

How should I format a date to always respect the specified format? [duplicate]

This question already has answers here:
Go time.Time.UTC() sometimes gives 7 digits, sometimes 9
(1 answer)
prevent json.Marshal time.Time removing trailing zeros
(1 answer)
Closed 2 months ago.
I have a Go API that is supposed to return a timestamp in the following format (Java notation but should be understandable):
yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'
My Go API will build this timestamp as follows:
func ParseToTimestamp(duration string, systemTime time.Time) (string, error) {
parsedDuration, err := time.ParseDuration(duration)
if err != nil {
return "", err
}
validity := systemTime.Add(parsedDuration)
return validity.Format("2006-01-02T15:04:05.999999Z"), nil
}
I've noticed, however, that this formatted string is not always respecting the wished format. For example, if I pass a date which has 0 nano-seconds:
duration := "10m"
systemTime := time.Date(1990, time.January, 24, 0, 0, 0, 0, time.UTC) //no nano-seconds
timestamp, _ := fxcash.ParseToTimestamp(duration, systemTime)
fmt.Println(timestamp)
>> 1990-01-24T00:10:00Z
However, if I pass a date which has 120k nano-seconds:
duration := "10m"
systemTime := time.Date(1990, time.January, 24, 0, 0, 0, 120000, time.UTC) //120k nano-seconds
timestamp, _ := fxcash.ParseToTimestamp(duration, systemTime)
fmt.Println(timestamp)
>> 1990-01-24T00:10:00.00012Z
Generally speaking, this causes an issue because the service that consumes my Go output expects to have exactly 6 nano-seconds, even if they were only zeros .000000Z.
Is there a way to do that without heavy parsing/ugly splitting using standard Go Libraries?
Sorry if this question is basic but I'm very new to Go, I've looked for examples on the web but couldn't find any.

RxJava - Count events on the fly

I would like to count objects passing from observable. I know there is a count operator but that can't be used for infinite streams because it waits for completition.
What I want is something like Value -> operator -> Pair(Int, Value). I know there could be a problem with int (or long) overflow and that is maybe a reason nothing like this exists but I still have feeling I've seen something like this before. One can implement this with scan operator but I thought there is a simpler way.
Output would be like:
Observable.just(Event1, Event2, Event3) -> (1, Event1), (2, Event2), (3, Event3)
You can solve your problem using the RxJava Scan method:
Observable.just("a", "b", "c")
.scan(new Pair<>(0, ""), (pair, s) -> new Pair<>(pair.first + 1, s))
.skip(1)
Pair<>(0, "") is your seed value
Lambda (pair, s) -> new Pair<>(pair.first + 1, s) takes the seed value and value emitted by original observable and then produces the next Pair value to be emitted and fed back into the lambda
Skip(1) is needed to avoid emitting the seed value
Count means a state change. So you can use a "stateful" map instead of an anonymous class.
ex:
class Mapper<T, R>(val mapper: (T) -> R) : Function<T, Pair<Int, R>> {
private var counter = 0
override fun apply(t: T): Pair<Int, R> {
return Pair(counter++, mapper(t))
//or ++counter if you want start from 1 instead of zero
}
}
//usage
val mapper = Mapper<String, String> { it.toUpperCase() }
Observable.just("a", "b", "c")
.map(mapper)
.subscribe {
Log.d("test logger", it.toString())
}

Go time comparison

I'm trying to create simple function just to change time zone of a time to another (Lets assume UTC to +0700 WIB). Here is the source code. I have 2 functions, first GenerateWIB which will change just your time zone into +0700 WIB with same datetime. Second is GenerateUTC which will change given time's timezone into UTC. GenerateUTC works perfectly while another is not.
expect := time.Date(2016, 12, 12, 1, 2, 3, 4, wib)
t1 := time.Date(2016, 12, 12, 1, 2, 3, 4, time.UTC)
res := GenerateWIB(t1)
if res != expect {
fmt.Printf("WIB Expect %+v, but get %+v", expect, res)
}
The res != expect always fullfilled with this result.
WIB Expect 2016-12-12 01:02:03.000000004 +0700 WIB, but get 2016-12-12 01:02:03.000000004 +0700 WIB
But it is the same time right? Did i miss something?
There is an .Equal() method to compare dates :
if !res.Equal(expect) {
...
Quoting the doc :
Note that the Go == operator compares not just the time instant but also the Location and the monotonic clock reading. Therefore, Time values should not be used as map or database keys without first guaranteeing that the identical Location has been set for all values, which can be achieved through use of the UTC or Local method, and that the monotonic clock reading has been stripped by setting t = t.Round(0). In general, prefer t.Equal(u) to t == u, since t.Equal uses the most accurate comparison available and correctly handles the case when only one of its arguments has a monotonic clock reading.
If you look at the code for the time.Time(*) struct, you can see that this struct has three private fields :
type Time struct {
...
wall uint64
ext int64
...
loc *Location
}
and the comments about those fields clearly indicate that, depending on how the Time struct was built, two Time describing the same point in time may have different values for these fields.
Running res == expect compares the values of these inner fields,
running res.Equal(expect) tries to do the thing you expect.
(*) time/time.go source code on master branch as of oct 27th, 2020
Dates in golang must be compared with Equal method. Method Date returns Time type.
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
and Time type have Equal method.
func (t Time) Equal(u Time) bool
Equal reports whether t and u represent the same time instant. Two times can be equal even if they are in different locations. For example, 6:00 +0200 CEST and 4:00 UTC are Equal. See the documentation on the Time type for the pitfalls of using == with Time values; most code should use Equal instead.
Example
package main
import (
"fmt"
"time"
)
func main() {
secondsEastOfUTC := int((8 * time.Hour).Seconds())
beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)
// Unlike the equal operator, Equal is aware that d1 and d2 are the
// same instant but in different time zones.
d1 := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
d2 := time.Date(2000, 2, 1, 20, 30, 0, 0, beijing)
datesEqualUsingEqualOperator := d1 == d2
datesEqualUsingFunction := d1.Equal(d2)
fmt.Printf("datesEqualUsingEqualOperator = %v\n", datesEqualUsingEqualOperator)
fmt.Printf("datesEqualUsingFunction = %v\n", datesEqualUsingFunction)
}
datesEqualUsingEqualOperator = false
datesEqualUsingFunction = true
resources
Time type documentation
Equal method documentation
time.Date

Coffee Script Array, Object

# String of Markdown in DB
beforeMark = #content
# Render string of markdown to html string
afterMark = marked(beforeMark)
# Parse the html to HTML to extract 0, 2, 4th children node (elements)
finalMark = $.parseHTML(afterMark)
# Help needed HERE
# Get 0 2 4th elements if they exist.
# ex) if array has 4 keys, return 0, 2th
# if array has 7 keys, return 0, 2, 4th
# if array has 3 keys, return 0, 2th
# if array has 1 key, return 0th
stringMark = $(finalMark[0]).prop('outerHTML') + $(finalMark[2]).prop('outerHTML') + $(finalMark[2]).prop('outerHTML')
I have the above coffeescript I wrote to truncate a markdown string into html of 3 elements.
I need the last part to be more efficient and proper so that it returns the 0, 2, 4th keys of arrays but only if they exist.
I am new to coffee and I need help!!
If I understand the problem correctly, I believe you want something like this:
stringMark = ''
for data, index in finalMark when index in [0, 2, 4]
stringMark += data.prop 'outerHTML'
Or if you like a little code golf:
stringMark = (v.prop 'outerHTML' for v, i in finalMark when i in [0, 2, 4]).join ''

Get same output as R console in Java using JRI

When I enter the following commands directly into the R console
library("xts")
mySeries <- xts(c(1.0, 2.0, 3.0, 5.0, 6.0), order.by=c(ISOdatetime(2001, 1, 1, 0, 0, 0), ISOdatetime(2001, 1, 2, 0, 0, 0), ISOdatetime(2001, 1, 3, 0, 0, 0), ISOdatetime(2001, 1, 4, 0, 0, 0), ISOdatetime(2001, 1, 5, 0, 0, 0)))
resultingSeries <- to.monthly(mySeries)
resultingSeries
I will get an output like this
mySeries.Open mySeries.High mySeries.Low mySeries.Close
Jan 2001 1 6 1 6
When I look into the attributes, I see the following output
attributes(resultingSeries)
$dim
[1] 1 4
$dimnames
$dimnames[[1]]
NULL
$dimnames[[2]]
[1] "mySeries.Open" "mySeries.High" "mySeries.Low" "mySeries.Close"
$index
[1] 978307200
attr(,"tclass")
[1] "yearmon"
$tclass
[1] "POSIXct" "POSIXt"
$tzone
[1] ""
$class
[1] "xts" "zoo"
$.indexCLASS
[1] "yearmon"
This is the same I get in Java. I'm wondering where the magic happens so that I see the nice output I get in R. I have no access to the event loop, since I'm using JRI like this (since, it's the recommended way and simplifies error handling):
REngine engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine");
REXP result = engine.parseAndEval(...)
/edit
In Java I execute each command from above as follows:
REXP result = engine.parseAndEval("resultingSeries") // or any other command
What I get is
org.rosuda.REngine.REXPDouble#4ac66122+[12]
The payload being doubles: 1, 6, 1, 6
The attributes are the same as specified above.
Now R does some magic to display the output above. Is there a way I can get the same output without having to create it manually by myself? Where's the implementation stored, that R gets the above mentioned output?
Here is a piece of code that will work, here i extracted the first element of the field mySeries.Open from the object resultingSeries (which i converted to a data frame) which is equal to 1, notice that you can't pass all of the resultingSeries object strait into Java, you will need to break it down.
package stackoverflow;
import org.rosuda.JRI.REXP;
import org.rosuda.JRI.Rengine;
/**
*
* #author yschellekens
*/
public class StackOverflow {
public static void main(String[] args) throws Exception {
String[] Rargs = {"--vanilla"};
Rengine rengine = new Rengine( Rargs, false, null);
rengine.eval("library('xts')");
rengine.eval("mySeries <- xts(c(1.0, 2.0, 3.0, 5.0, 6.0), order.by=c(ISOdatetime(2001, 1, 1, 0, 0, 0), ISOdatetime(2001, 1, 2, 0, 0, 0), ISOdatetime(2001, 1, 3, 0, 0, 0), ISOdatetime(2001, 1, 4, 0, 0, 0), ISOdatetime(2001, 1, 5, 0, 0, 0)))");
rengine.eval("resultingSeries <- to.monthly(mySeries)");
rengine.eval("resultingSeries<-as.data.frame(resultingSeries)");
REXP result= rengine.eval("resultingSeries$mySeries.Open");
System.out.println("Greeting from R: "+result.asDouble());
}
}
And the Java output:
run:
Greeting from R: 1.0
I figured out the following workaround. The solution is far from perfect.
R offers a command to save its console output as characters vector.
capture.output( {command} )
We can access the output using
REXPString s = rengine.parseAndEval("capture.output( to.monthly(mySeries))")
String[] output = result.asStrings()
The variable output will contain all output lines
[0] mySeries.Open mySeries.High mySeries.Low mySeries.Close
[1]Jan 2001 1 6 1 6
Alternatively you coud use JRIEngine and attack yourself to the event loop, which it did not want in my case (due to the more complicated error handling).

Resources